From d98b23dba0f311e6e1dce45cdfd171ab89646e21 Mon Sep 17 00:00:00 2001 From: Mike Kinney Date: Wed, 29 Dec 2021 21:56:03 -0800 Subject: [PATCH] remove docs dir --- docs/meshtastic/admin_pb2.html | 1118 -- docs/meshtastic/apponly_pb2.html | 707 -- docs/meshtastic/ble.html | 53 - docs/meshtastic/ble_interface.html | 212 - docs/meshtastic/channel_pb2.html | 1741 --- docs/meshtastic/deviceonly_pb2.html | 2241 ---- .../environmental_measurement_pb2.html | 746 -- docs/meshtastic/globals.html | 380 - docs/meshtastic/index.html | 538 - docs/meshtastic/mesh_interface.html | 1851 --- docs/meshtastic/mesh_pb2.html | 9935 ----------------- docs/meshtastic/mqtt_pb2.html | 759 -- docs/meshtastic/node.html | 1280 --- docs/meshtastic/portnums_pb2.html | 190 - docs/meshtastic/radioconfig_pb2.html | 1604 --- docs/meshtastic/remote_hardware.html | 324 - docs/meshtastic/remote_hardware_pb2.html | 822 -- docs/meshtastic/serial_interface.html | 254 - docs/meshtastic/storeforward_pb2.html | 1165 -- docs/meshtastic/stream_interface.html | 519 - docs/meshtastic/tcp_interface.html | 251 - docs/meshtastic/test.html | 544 - docs/meshtastic/tests/conftest.html | 199 - docs/meshtastic/tests/index.html | 142 - docs/meshtastic/tests/test_ble_interface.html | 95 - docs/meshtastic/tests/test_examples.html | 132 - docs/meshtastic/tests/test_globals.html | 130 - docs/meshtastic/tests/test_int.html | 177 - docs/meshtastic/tests/test_main.html | 4552 -------- .../meshtastic/tests/test_mesh_interface.html | 1290 --- docs/meshtastic/tests/test_node.html | 4143 ------- .../tests/test_remote_hardware.html | 304 - .../tests/test_serial_interface.html | 186 - docs/meshtastic/tests/test_smoke1.html | 1822 --- docs/meshtastic/tests/test_smoke2.html | 127 - docs/meshtastic/tests/test_smoke_wifi.html | 115 - .../tests/test_stream_interface.html | 246 - docs/meshtastic/tests/test_tcp_interface.html | 120 - docs/meshtastic/tests/test_util.html | 519 - docs/meshtastic/tunnel.html | 615 - docs/meshtastic/util.html | 688 -- 41 files changed, 42836 deletions(-) delete mode 100644 docs/meshtastic/admin_pb2.html delete mode 100644 docs/meshtastic/apponly_pb2.html delete mode 100644 docs/meshtastic/ble.html delete mode 100644 docs/meshtastic/ble_interface.html delete mode 100644 docs/meshtastic/channel_pb2.html delete mode 100644 docs/meshtastic/deviceonly_pb2.html delete mode 100644 docs/meshtastic/environmental_measurement_pb2.html delete mode 100644 docs/meshtastic/globals.html delete mode 100644 docs/meshtastic/index.html delete mode 100644 docs/meshtastic/mesh_interface.html delete mode 100644 docs/meshtastic/mesh_pb2.html delete mode 100644 docs/meshtastic/mqtt_pb2.html delete mode 100644 docs/meshtastic/node.html delete mode 100644 docs/meshtastic/portnums_pb2.html delete mode 100644 docs/meshtastic/radioconfig_pb2.html delete mode 100644 docs/meshtastic/remote_hardware.html delete mode 100644 docs/meshtastic/remote_hardware_pb2.html delete mode 100644 docs/meshtastic/serial_interface.html delete mode 100644 docs/meshtastic/storeforward_pb2.html delete mode 100644 docs/meshtastic/stream_interface.html delete mode 100644 docs/meshtastic/tcp_interface.html delete mode 100644 docs/meshtastic/test.html delete mode 100644 docs/meshtastic/tests/conftest.html delete mode 100644 docs/meshtastic/tests/index.html delete mode 100644 docs/meshtastic/tests/test_ble_interface.html delete mode 100644 docs/meshtastic/tests/test_examples.html delete mode 100644 docs/meshtastic/tests/test_globals.html delete mode 100644 docs/meshtastic/tests/test_int.html delete mode 100644 docs/meshtastic/tests/test_main.html delete mode 100644 docs/meshtastic/tests/test_mesh_interface.html delete mode 100644 docs/meshtastic/tests/test_node.html delete mode 100644 docs/meshtastic/tests/test_remote_hardware.html delete mode 100644 docs/meshtastic/tests/test_serial_interface.html delete mode 100644 docs/meshtastic/tests/test_smoke1.html delete mode 100644 docs/meshtastic/tests/test_smoke2.html delete mode 100644 docs/meshtastic/tests/test_smoke_wifi.html delete mode 100644 docs/meshtastic/tests/test_stream_interface.html delete mode 100644 docs/meshtastic/tests/test_tcp_interface.html delete mode 100644 docs/meshtastic/tests/test_util.html delete mode 100644 docs/meshtastic/tunnel.html delete mode 100644 docs/meshtastic/util.html diff --git a/docs/meshtastic/admin_pb2.html b/docs/meshtastic/admin_pb2.html deleted file mode 100644 index 1c05faa..0000000 --- a/docs/meshtastic/admin_pb2.html +++ /dev/null @@ -1,1118 +0,0 @@ - - - - - - -meshtastic.admin_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.admin_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: admin.proto
-
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-from . import channel_pb2 as channel__pb2
-from . import radioconfig_pb2 as radioconfig__pb2
-from . import mesh_pb2 as mesh__pb2
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='admin.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\013AdminProtosH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\x0b\x61\x64min.proto\x1a\rchannel.proto\x1a\x11radioconfig.proto\x1a\nmesh.proto\"\xbd\x03\n\x0c\x41\x64minMessage\x12!\n\tset_radio\x18\x01 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1a\n\tset_owner\x18\x02 \x01(\x0b\x32\x05.UserH\x00\x12\x1f\n\x0bset_channel\x18\x03 \x01(\x0b\x32\x08.ChannelH\x00\x12\x1b\n\x11get_radio_request\x18\x04 \x01(\x08H\x00\x12*\n\x12get_radio_response\x18\x05 \x01(\x0b\x32\x0c.RadioConfigH\x00\x12\x1d\n\x13get_channel_request\x18\x06 \x01(\rH\x00\x12(\n\x14get_channel_response\x18\x07 \x01(\x0b\x32\x08.ChannelH\x00\x12\x1b\n\x11get_owner_request\x18\x08 \x01(\x08H\x00\x12#\n\x12get_owner_response\x18\t \x01(\x0b\x32\x05.UserH\x00\x12\x1d\n\x13\x63onfirm_set_channel\x18  \x01(\x08H\x00\x12\x1b\n\x11\x63onfirm_set_radio\x18! \x01(\x08H\x00\x12\x18\n\x0e\x65xit_simulator\x18\" \x01(\x08H\x00\x12\x18\n\x0ereboot_seconds\x18# \x01(\x05H\x00\x42\t\n\x07variantBG\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-  ,
-  dependencies=[channel__pb2.DESCRIPTOR,radioconfig__pb2.DESCRIPTOR,mesh__pb2.DESCRIPTOR,])
-
-
-
-
-_ADMINMESSAGE = _descriptor.Descriptor(
-  name='AdminMessage',
-  full_name='AdminMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='set_radio', full_name='AdminMessage.set_radio', index=0,
-      number=1, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='set_owner', full_name='AdminMessage.set_owner', index=1,
-      number=2, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='set_channel', full_name='AdminMessage.set_channel', index=2,
-      number=3, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='get_radio_request', full_name='AdminMessage.get_radio_request', index=3,
-      number=4, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='get_radio_response', full_name='AdminMessage.get_radio_response', index=4,
-      number=5, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='get_channel_request', full_name='AdminMessage.get_channel_request', index=5,
-      number=6, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='get_channel_response', full_name='AdminMessage.get_channel_response', index=6,
-      number=7, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='get_owner_request', full_name='AdminMessage.get_owner_request', index=7,
-      number=8, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='get_owner_response', full_name='AdminMessage.get_owner_response', index=8,
-      number=9, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='confirm_set_channel', full_name='AdminMessage.confirm_set_channel', index=9,
-      number=32, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='confirm_set_radio', full_name='AdminMessage.confirm_set_radio', index=10,
-      number=33, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='exit_simulator', full_name='AdminMessage.exit_simulator', index=11,
-      number=34, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='reboot_seconds', full_name='AdminMessage.reboot_seconds', index=12,
-      number=35, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-    _descriptor.OneofDescriptor(
-      name='variant', full_name='AdminMessage.variant',
-      index=0, containing_type=None, fields=[]),
-  ],
-  serialized_start=62,
-  serialized_end=507,
-)
-
-_ADMINMESSAGE.fields_by_name['set_radio'].message_type = radioconfig__pb2._RADIOCONFIG
-_ADMINMESSAGE.fields_by_name['set_owner'].message_type = mesh__pb2._USER
-_ADMINMESSAGE.fields_by_name['set_channel'].message_type = channel__pb2._CHANNEL
-_ADMINMESSAGE.fields_by_name['get_radio_response'].message_type = radioconfig__pb2._RADIOCONFIG
-_ADMINMESSAGE.fields_by_name['get_channel_response'].message_type = channel__pb2._CHANNEL
-_ADMINMESSAGE.fields_by_name['get_owner_response'].message_type = mesh__pb2._USER
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['set_radio'])
-_ADMINMESSAGE.fields_by_name['set_radio'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['set_owner'])
-_ADMINMESSAGE.fields_by_name['set_owner'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['set_channel'])
-_ADMINMESSAGE.fields_by_name['set_channel'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['get_radio_request'])
-_ADMINMESSAGE.fields_by_name['get_radio_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['get_radio_response'])
-_ADMINMESSAGE.fields_by_name['get_radio_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['get_channel_request'])
-_ADMINMESSAGE.fields_by_name['get_channel_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['get_channel_response'])
-_ADMINMESSAGE.fields_by_name['get_channel_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['get_owner_request'])
-_ADMINMESSAGE.fields_by_name['get_owner_request'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['get_owner_response'])
-_ADMINMESSAGE.fields_by_name['get_owner_response'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['confirm_set_channel'])
-_ADMINMESSAGE.fields_by_name['confirm_set_channel'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['confirm_set_radio'])
-_ADMINMESSAGE.fields_by_name['confirm_set_radio'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['exit_simulator'])
-_ADMINMESSAGE.fields_by_name['exit_simulator'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-_ADMINMESSAGE.oneofs_by_name['variant'].fields.append(
-  _ADMINMESSAGE.fields_by_name['reboot_seconds'])
-_ADMINMESSAGE.fields_by_name['reboot_seconds'].containing_oneof = _ADMINMESSAGE.oneofs_by_name['variant']
-DESCRIPTOR.message_types_by_name['AdminMessage'] = _ADMINMESSAGE
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-AdminMessage = _reflection.GeneratedProtocolMessageType('AdminMessage', (_message.Message,), {
-  'DESCRIPTOR' : _ADMINMESSAGE,
-  '__module__' : 'admin_pb2'
-  # @@protoc_insertion_point(class_scope:AdminMessage)
-  })
-_sym_db.RegisterMessage(AdminMessage)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AdminMessage -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var CONFIRM_SET_CHANNEL_FIELD_NUMBER
-
-
-
-
var CONFIRM_SET_RADIO_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
var EXIT_SIMULATOR_FIELD_NUMBER
-
-
-
-
var GET_CHANNEL_REQUEST_FIELD_NUMBER
-
-
-
-
var GET_CHANNEL_RESPONSE_FIELD_NUMBER
-
-
-
-
var GET_OWNER_REQUEST_FIELD_NUMBER
-
-
-
-
var GET_OWNER_RESPONSE_FIELD_NUMBER
-
-
-
-
var GET_RADIO_REQUEST_FIELD_NUMBER
-
-
-
-
var GET_RADIO_RESPONSE_FIELD_NUMBER
-
-
-
-
var REBOOT_SECONDS_FIELD_NUMBER
-
-
-
-
var SET_CHANNEL_FIELD_NUMBER
-
-
-
-
var SET_OWNER_FIELD_NUMBER
-
-
-
-
var SET_RADIO_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var confirm_set_channel
-
-

Getter for confirm_set_channel.

-
- -Expand source code - -
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)
-
-
-
var confirm_set_radio
-
-

Getter for confirm_set_radio.

-
- -Expand source code - -
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)
-
-
-
var exit_simulator
-
-

Getter for exit_simulator.

-
- -Expand source code - -
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)
-
-
-
var get_channel_request
-
-

Getter for get_channel_request.

-
- -Expand source code - -
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)
-
-
-
var get_channel_response
-
-

Getter for get_channel_response.

-
- -Expand source code - -
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
-
-
-
var get_owner_request
-
-

Getter for get_owner_request.

-
- -Expand source code - -
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)
-
-
-
var get_owner_response
-
-

Getter for get_owner_response.

-
- -Expand source code - -
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
-
-
-
var get_radio_request
-
-

Getter for get_radio_request.

-
- -Expand source code - -
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)
-
-
-
var get_radio_response
-
-

Getter for get_radio_response.

-
- -Expand source code - -
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
-
-
-
var reboot_seconds
-
-

Getter for reboot_seconds.

-
- -Expand source code - -
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)
-
-
-
var set_channel
-
-

Getter for set_channel.

-
- -Expand source code - -
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
-
-
-
var set_owner
-
-

Getter for set_owner.

-
- -Expand source code - -
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
-
-
-
var set_radio
-
-

Getter for set_radio.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/apponly_pb2.html b/docs/meshtastic/apponly_pb2.html deleted file mode 100644 index 1180130..0000000 --- a/docs/meshtastic/apponly_pb2.html +++ /dev/null @@ -1,707 +0,0 @@ - - - - - - -meshtastic.apponly_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.apponly_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: apponly.proto
-
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-from . import channel_pb2 as channel__pb2
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='apponly.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\rAppOnlyProtosH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\rapponly.proto\x1a\rchannel.proto\"0\n\nChannelSet\x12\"\n\x08settings\x18\x01 \x03(\x0b\x32\x10.ChannelSettingsBI\n\x13\x63om.geeksville.meshB\rAppOnlyProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-  ,
-  dependencies=[channel__pb2.DESCRIPTOR,])
-
-
-
-
-_CHANNELSET = _descriptor.Descriptor(
-  name='ChannelSet',
-  full_name='ChannelSet',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='settings', full_name='ChannelSet.settings', index=0,
-      number=1, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=32,
-  serialized_end=80,
-)
-
-_CHANNELSET.fields_by_name['settings'].message_type = channel__pb2._CHANNELSETTINGS
-DESCRIPTOR.message_types_by_name['ChannelSet'] = _CHANNELSET
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-ChannelSet = _reflection.GeneratedProtocolMessageType('ChannelSet', (_message.Message,), {
-  'DESCRIPTOR' : _CHANNELSET,
-  '__module__' : 'apponly_pb2'
-  # @@protoc_insertion_point(class_scope:ChannelSet)
-  })
-_sym_db.RegisterMessage(ChannelSet)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class ChannelSet -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var SETTINGS_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var settings
-
-

Getter for settings.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/ble.html b/docs/meshtastic/ble.html deleted file mode 100644 index 154731f..0000000 --- a/docs/meshtastic/ble.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - -meshtastic.ble API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.ble

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/ble_interface.html b/docs/meshtastic/ble_interface.html deleted file mode 100644 index 7bf14a3..0000000 --- a/docs/meshtastic/ble_interface.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - -meshtastic.ble_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.ble_interface

-
-
-

Bluetooth interface

-
- -Expand source code - -
"""Bluetooth interface
-"""
-import logging
-import pygatt
-
-
-from .mesh_interface import MeshInterface
-
-# Our standard BLE characteristics
-TORADIO_UUID = "f75c76d2-129e-4dad-a1dd-7866124401e7"
-FROMRADIO_UUID = "8ba2bcc2-ee02-4a55-a531-c525c5e454d5"
-FROMNUM_UUID = "ed9da18c-a800-4f66-a670-aa7547e34453"
-
-
-class BLEInterface(MeshInterface):
-    """A not quite ready - FIXME - BLE interface to devices"""
-
-    def __init__(self, address, noProto=False, debugOut=None):
-        self.address = address
-        if not noProto:
-            self.adapter = pygatt.GATTToolBackend()  # BGAPIBackend()
-            self.adapter.start()
-            logging.debug(f"Connecting to {self.address}")
-            self.device = self.adapter.connect(address)
-        else:
-            self.adapter = None
-            self.device = None
-        logging.debug("Connected to device")
-        # fromradio = self.device.char_read(FROMRADIO_UUID)
-        MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
-
-        self._readFromRadio()  # read the initial responses
-
-        def handle_data(handle, data):
-            self._handleFromRadio(data)
-
-        if self.device:
-            self.device.subscribe(FROMNUM_UUID, callback=handle_data)
-
-    def _sendToRadioImpl(self, toRadio):
-        """Send a ToRadio protobuf to the device"""
-        #logging.debug(f"Sending: {stripnl(toRadio)}")
-        b = toRadio.SerializeToString()
-        self.device.char_write(TORADIO_UUID, b)
-
-    def close(self):
-        MeshInterface.close(self)
-        if self.adapter:
-            self.adapter.stop()
-
-    def _readFromRadio(self):
-        if not self.noProto:
-            wasEmpty = False
-            while not wasEmpty:
-                if self.device:
-                    b = self.device.char_read(FROMRADIO_UUID)
-                    wasEmpty = len(b) == 0
-                    if not wasEmpty:
-                        self._handleFromRadio(b)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class BLEInterface -(address, noProto=False, debugOut=None) -
-
-

A not quite ready - FIXME - BLE interface to devices

-

Constructor

-

Keyword Arguments: -noProto – If True, don't try to run our protocol on the -link - just be a dumb serial client.

-
- -Expand source code - -
class BLEInterface(MeshInterface):
-    """A not quite ready - FIXME - BLE interface to devices"""
-
-    def __init__(self, address, noProto=False, debugOut=None):
-        self.address = address
-        if not noProto:
-            self.adapter = pygatt.GATTToolBackend()  # BGAPIBackend()
-            self.adapter.start()
-            logging.debug(f"Connecting to {self.address}")
-            self.device = self.adapter.connect(address)
-        else:
-            self.adapter = None
-            self.device = None
-        logging.debug("Connected to device")
-        # fromradio = self.device.char_read(FROMRADIO_UUID)
-        MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
-
-        self._readFromRadio()  # read the initial responses
-
-        def handle_data(handle, data):
-            self._handleFromRadio(data)
-
-        if self.device:
-            self.device.subscribe(FROMNUM_UUID, callback=handle_data)
-
-    def _sendToRadioImpl(self, toRadio):
-        """Send a ToRadio protobuf to the device"""
-        #logging.debug(f"Sending: {stripnl(toRadio)}")
-        b = toRadio.SerializeToString()
-        self.device.char_write(TORADIO_UUID, b)
-
-    def close(self):
-        MeshInterface.close(self)
-        if self.adapter:
-            self.adapter.stop()
-
-    def _readFromRadio(self):
-        if not self.noProto:
-            wasEmpty = False
-            while not wasEmpty:
-                if self.device:
-                    b = self.device.char_read(FROMRADIO_UUID)
-                    wasEmpty = len(b) == 0
-                    if not wasEmpty:
-                        self._handleFromRadio(b)
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/channel_pb2.html b/docs/meshtastic/channel_pb2.html deleted file mode 100644 index f717c6d..0000000 --- a/docs/meshtastic/channel_pb2.html +++ /dev/null @@ -1,1741 +0,0 @@ - - - - - - -meshtastic.channel_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.channel_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: channel.proto
-
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='channel.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\rChannelProtosH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\rchannel.proto\"\x91\x03\n\x0f\x43hannelSettings\x12\x10\n\x08tx_power\x18\x01 \x01(\x05\x12\x32\n\x0cmodem_config\x18\x03 \x01(\x0e\x32\x1c.ChannelSettings.ModemConfig\x12\x11\n\tbandwidth\x18\x06 \x01(\r\x12\x15\n\rspread_factor\x18\x07 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x08 \x01(\r\x12\x13\n\x0b\x63hannel_num\x18\t \x01(\r\x12\x0b\n\x03psk\x18\x04 \x01(\x0c\x12\x0c\n\x04name\x18\x05 \x01(\t\x12\n\n\x02id\x18\n \x01(\x07\x12\x16\n\x0euplink_enabled\x18\x10 \x01(\x08\x12\x18\n\x10\x64ownlink_enabled\x18\x11 \x01(\x08\"\x8a\x01\n\x0bModemConfig\x12\x12\n\x0e\x42w125Cr45Sf128\x10\x00\x12\x12\n\x0e\x42w500Cr45Sf128\x10\x01\x12\x14\n\x10\x42w31_25Cr48Sf512\x10\x02\x12\x13\n\x0f\x42w125Cr48Sf4096\x10\x03\x12\x13\n\x0f\x42w250Cr46Sf2048\x10\x04\x12\x13\n\x0f\x42w250Cr47Sf1024\x10\x05\"\x8b\x01\n\x07\x43hannel\x12\r\n\x05index\x18\x01 \x01(\x05\x12\"\n\x08settings\x18\x02 \x01(\x0b\x32\x10.ChannelSettings\x12\x1b\n\x04role\x18\x03 \x01(\x0e\x32\r.Channel.Role\"0\n\x04Role\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07PRIMARY\x10\x01\x12\r\n\tSECONDARY\x10\x02\x42I\n\x13\x63om.geeksville.meshB\rChannelProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-)
-
-
-
-_CHANNELSETTINGS_MODEMCONFIG = _descriptor.EnumDescriptor(
-  name='ModemConfig',
-  full_name='ChannelSettings.ModemConfig',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='Bw125Cr45Sf128', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='Bw500Cr45Sf128', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='Bw31_25Cr48Sf512', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='Bw125Cr48Sf4096', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='Bw250Cr46Sf2048', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='Bw250Cr47Sf1024', index=5, number=5,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=281,
-  serialized_end=419,
-)
-_sym_db.RegisterEnumDescriptor(_CHANNELSETTINGS_MODEMCONFIG)
-
-_CHANNEL_ROLE = _descriptor.EnumDescriptor(
-  name='Role',
-  full_name='Channel.Role',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='DISABLED', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='PRIMARY', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='SECONDARY', index=2, number=2,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=513,
-  serialized_end=561,
-)
-_sym_db.RegisterEnumDescriptor(_CHANNEL_ROLE)
-
-
-_CHANNELSETTINGS = _descriptor.Descriptor(
-  name='ChannelSettings',
-  full_name='ChannelSettings',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='tx_power', full_name='ChannelSettings.tx_power', index=0,
-      number=1, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='modem_config', full_name='ChannelSettings.modem_config', index=1,
-      number=3, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='bandwidth', full_name='ChannelSettings.bandwidth', index=2,
-      number=6, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='spread_factor', full_name='ChannelSettings.spread_factor', index=3,
-      number=7, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='coding_rate', full_name='ChannelSettings.coding_rate', index=4,
-      number=8, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='channel_num', full_name='ChannelSettings.channel_num', index=5,
-      number=9, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='psk', full_name='ChannelSettings.psk', index=6,
-      number=4, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"",
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='name', full_name='ChannelSettings.name', index=7,
-      number=5, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='id', full_name='ChannelSettings.id', index=8,
-      number=10, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='uplink_enabled', full_name='ChannelSettings.uplink_enabled', index=9,
-      number=16, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='downlink_enabled', full_name='ChannelSettings.downlink_enabled', index=10,
-      number=17, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-    _CHANNELSETTINGS_MODEMCONFIG,
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=18,
-  serialized_end=419,
-)
-
-
-_CHANNEL = _descriptor.Descriptor(
-  name='Channel',
-  full_name='Channel',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='index', full_name='Channel.index', index=0,
-      number=1, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='settings', full_name='Channel.settings', index=1,
-      number=2, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='role', full_name='Channel.role', index=2,
-      number=3, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-    _CHANNEL_ROLE,
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=422,
-  serialized_end=561,
-)
-
-_CHANNELSETTINGS.fields_by_name['modem_config'].enum_type = _CHANNELSETTINGS_MODEMCONFIG
-_CHANNELSETTINGS_MODEMCONFIG.containing_type = _CHANNELSETTINGS
-_CHANNEL.fields_by_name['settings'].message_type = _CHANNELSETTINGS
-_CHANNEL.fields_by_name['role'].enum_type = _CHANNEL_ROLE
-_CHANNEL_ROLE.containing_type = _CHANNEL
-DESCRIPTOR.message_types_by_name['ChannelSettings'] = _CHANNELSETTINGS
-DESCRIPTOR.message_types_by_name['Channel'] = _CHANNEL
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-ChannelSettings = _reflection.GeneratedProtocolMessageType('ChannelSettings', (_message.Message,), {
-  'DESCRIPTOR' : _CHANNELSETTINGS,
-  '__module__' : 'channel_pb2'
-  # @@protoc_insertion_point(class_scope:ChannelSettings)
-  })
-_sym_db.RegisterMessage(ChannelSettings)
-
-Channel = _reflection.GeneratedProtocolMessageType('Channel', (_message.Message,), {
-  'DESCRIPTOR' : _CHANNEL,
-  '__module__' : 'channel_pb2'
-  # @@protoc_insertion_point(class_scope:Channel)
-  })
-_sym_db.RegisterMessage(Channel)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Channel -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var DISABLED
-
-
-
-
var INDEX_FIELD_NUMBER
-
-
-
-
var PRIMARY
-
-
-
-
var ROLE_FIELD_NUMBER
-
-
-
-
var Role
-
-
-
-
var SECONDARY
-
-
-
-
var SETTINGS_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var index
-
-

Getter for index.

-
- -Expand source code - -
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)
-
-
-
var role
-
-

Getter for role.

-
- -Expand source code - -
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)
-
-
-
var settings
-
-

Getter for settings.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class ChannelSettings -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var BANDWIDTH_FIELD_NUMBER
-
-
-
-
var Bw125Cr45Sf128
-
-
-
-
var Bw125Cr48Sf4096
-
-
-
-
var Bw250Cr46Sf2048
-
-
-
-
var Bw250Cr47Sf1024
-
-
-
-
var Bw31_25Cr48Sf512
-
-
-
-
var Bw500Cr45Sf128
-
-
-
-
var CHANNEL_NUM_FIELD_NUMBER
-
-
-
-
var CODING_RATE_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
- -
-
-
-
var ID_FIELD_NUMBER
-
-
-
-
var MODEM_CONFIG_FIELD_NUMBER
-
-
-
-
var ModemConfig
-
-
-
-
var NAME_FIELD_NUMBER
-
-
-
-
var PSK_FIELD_NUMBER
-
-
-
-
var SPREAD_FACTOR_FIELD_NUMBER
-
-
-
-
var TX_POWER_FIELD_NUMBER
-
-
-
- -
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var bandwidth
-
-

Getter for bandwidth.

-
- -Expand source code - -
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)
-
-
-
var channel_num
-
-

Getter for channel_num.

-
- -Expand source code - -
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)
-
-
-
var coding_rate
-
-

Getter for coding_rate.

-
- -Expand source code - -
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)
-
-
- -
-

Getter for downlink_enabled.

-
- -Expand source code - -
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)
-
-
-
var id
-
-

Getter for id.

-
- -Expand source code - -
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)
-
-
-
var modem_config
-
-

Getter for modem_config.

-
- -Expand source code - -
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)
-
-
-
var name
-
-

Getter for name.

-
- -Expand source code - -
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)
-
-
-
var psk
-
-

Getter for psk.

-
- -Expand source code - -
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)
-
-
-
var spread_factor
-
-

Getter for spread_factor.

-
- -Expand source code - -
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)
-
-
-
var tx_power
-
-

Getter for tx_power.

-
- -Expand source code - -
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)
-
-
- -
-

Getter for uplink_enabled.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/deviceonly_pb2.html b/docs/meshtastic/deviceonly_pb2.html deleted file mode 100644 index 6b4df19..0000000 --- a/docs/meshtastic/deviceonly_pb2.html +++ /dev/null @@ -1,2241 +0,0 @@ - - - - - - -meshtastic.deviceonly_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.deviceonly_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: deviceonly.proto
-
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-from . import channel_pb2 as channel__pb2
-from . import mesh_pb2 as mesh__pb2
-from . import radioconfig_pb2 as radioconfig__pb2
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='deviceonly.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\nDeviceOnlyH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\x10\x64\x65viceonly.proto\x1a\rchannel.proto\x1a\nmesh.proto\x1a\x11radioconfig.proto\"\x80\x01\n\x11LegacyRadioConfig\x12\x39\n\x0bpreferences\x18\x01 \x01(\x0b\x32$.LegacyRadioConfig.LegacyPreferences\x1a\x30\n\x11LegacyPreferences\x12\x1b\n\x06region\x18\x0f \x01(\x0e\x32\x0b.RegionCode\"\x8f\x02\n\x0b\x44\x65viceState\x12\'\n\x0blegacyRadio\x18\x01 \x01(\x0b\x32\x12.LegacyRadioConfig\x12\x1c\n\x07my_node\x18\x02 \x01(\x0b\x32\x0b.MyNodeInfo\x12\x14\n\x05owner\x18\x03 \x01(\x0b\x32\x05.User\x12\x1a\n\x07node_db\x18\x04 \x03(\x0b\x32\t.NodeInfo\x12\"\n\rreceive_queue\x18\x05 \x03(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07version\x18\x08 \x01(\r\x12$\n\x0frx_text_message\x18\x07 \x01(\x0b\x32\x0b.MeshPacket\x12\x0f\n\x07no_save\x18\t \x01(\x08\x12\x15\n\rdid_gps_reset\x18\x0b \x01(\x08J\x04\x08\x0c\x10\r\")\n\x0b\x43hannelFile\x12\x1a\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x08.ChannelBF\n\x13\x63om.geeksville.meshB\nDeviceOnlyH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-  ,
-  dependencies=[channel__pb2.DESCRIPTOR,mesh__pb2.DESCRIPTOR,radioconfig__pb2.DESCRIPTOR,])
-
-
-
-
-_LEGACYRADIOCONFIG_LEGACYPREFERENCES = _descriptor.Descriptor(
-  name='LegacyPreferences',
-  full_name='LegacyRadioConfig.LegacyPreferences',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='region', full_name='LegacyRadioConfig.LegacyPreferences.region', index=0,
-      number=15, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=147,
-  serialized_end=195,
-)
-
-_LEGACYRADIOCONFIG = _descriptor.Descriptor(
-  name='LegacyRadioConfig',
-  full_name='LegacyRadioConfig',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='preferences', full_name='LegacyRadioConfig.preferences', index=0,
-      number=1, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[_LEGACYRADIOCONFIG_LEGACYPREFERENCES, ],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=67,
-  serialized_end=195,
-)
-
-
-_DEVICESTATE = _descriptor.Descriptor(
-  name='DeviceState',
-  full_name='DeviceState',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='legacyRadio', full_name='DeviceState.legacyRadio', index=0,
-      number=1, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='my_node', full_name='DeviceState.my_node', index=1,
-      number=2, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='owner', full_name='DeviceState.owner', index=2,
-      number=3, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='node_db', full_name='DeviceState.node_db', index=3,
-      number=4, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='receive_queue', full_name='DeviceState.receive_queue', index=4,
-      number=5, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='version', full_name='DeviceState.version', index=5,
-      number=8, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='rx_text_message', full_name='DeviceState.rx_text_message', index=6,
-      number=7, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='no_save', full_name='DeviceState.no_save', index=7,
-      number=9, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='did_gps_reset', full_name='DeviceState.did_gps_reset', index=8,
-      number=11, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=198,
-  serialized_end=469,
-)
-
-
-_CHANNELFILE = _descriptor.Descriptor(
-  name='ChannelFile',
-  full_name='ChannelFile',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='channels', full_name='ChannelFile.channels', index=0,
-      number=1, type=11, cpp_type=10, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=471,
-  serialized_end=512,
-)
-
-_LEGACYRADIOCONFIG_LEGACYPREFERENCES.fields_by_name['region'].enum_type = radioconfig__pb2._REGIONCODE
-_LEGACYRADIOCONFIG_LEGACYPREFERENCES.containing_type = _LEGACYRADIOCONFIG
-_LEGACYRADIOCONFIG.fields_by_name['preferences'].message_type = _LEGACYRADIOCONFIG_LEGACYPREFERENCES
-_DEVICESTATE.fields_by_name['legacyRadio'].message_type = _LEGACYRADIOCONFIG
-_DEVICESTATE.fields_by_name['my_node'].message_type = mesh__pb2._MYNODEINFO
-_DEVICESTATE.fields_by_name['owner'].message_type = mesh__pb2._USER
-_DEVICESTATE.fields_by_name['node_db'].message_type = mesh__pb2._NODEINFO
-_DEVICESTATE.fields_by_name['receive_queue'].message_type = mesh__pb2._MESHPACKET
-_DEVICESTATE.fields_by_name['rx_text_message'].message_type = mesh__pb2._MESHPACKET
-_CHANNELFILE.fields_by_name['channels'].message_type = channel__pb2._CHANNEL
-DESCRIPTOR.message_types_by_name['LegacyRadioConfig'] = _LEGACYRADIOCONFIG
-DESCRIPTOR.message_types_by_name['DeviceState'] = _DEVICESTATE
-DESCRIPTOR.message_types_by_name['ChannelFile'] = _CHANNELFILE
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-LegacyRadioConfig = _reflection.GeneratedProtocolMessageType('LegacyRadioConfig', (_message.Message,), {
-
-  'LegacyPreferences' : _reflection.GeneratedProtocolMessageType('LegacyPreferences', (_message.Message,), {
-    'DESCRIPTOR' : _LEGACYRADIOCONFIG_LEGACYPREFERENCES,
-    '__module__' : 'deviceonly_pb2'
-    # @@protoc_insertion_point(class_scope:LegacyRadioConfig.LegacyPreferences)
-    })
-  ,
-  'DESCRIPTOR' : _LEGACYRADIOCONFIG,
-  '__module__' : 'deviceonly_pb2'
-  # @@protoc_insertion_point(class_scope:LegacyRadioConfig)
-  })
-_sym_db.RegisterMessage(LegacyRadioConfig)
-_sym_db.RegisterMessage(LegacyRadioConfig.LegacyPreferences)
-
-DeviceState = _reflection.GeneratedProtocolMessageType('DeviceState', (_message.Message,), {
-  'DESCRIPTOR' : _DEVICESTATE,
-  '__module__' : 'deviceonly_pb2'
-  # @@protoc_insertion_point(class_scope:DeviceState)
-  })
-_sym_db.RegisterMessage(DeviceState)
-
-ChannelFile = _reflection.GeneratedProtocolMessageType('ChannelFile', (_message.Message,), {
-  'DESCRIPTOR' : _CHANNELFILE,
-  '__module__' : 'deviceonly_pb2'
-  # @@protoc_insertion_point(class_scope:ChannelFile)
-  })
-_sym_db.RegisterMessage(ChannelFile)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class ChannelFile -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var CHANNELS_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var channels
-
-

Getter for channels.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class DeviceState -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var DID_GPS_RESET_FIELD_NUMBER
-
-
-
-
var LEGACYRADIO_FIELD_NUMBER
-
-
-
-
var MY_NODE_FIELD_NUMBER
-
-
-
-
var NODE_DB_FIELD_NUMBER
-
-
-
-
var NO_SAVE_FIELD_NUMBER
-
-
-
-
var OWNER_FIELD_NUMBER
-
-
-
-
var RECEIVE_QUEUE_FIELD_NUMBER
-
-
-
-
var RX_TEXT_MESSAGE_FIELD_NUMBER
-
-
-
-
var VERSION_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var did_gps_reset
-
-

Getter for did_gps_reset.

-
- -Expand source code - -
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)
-
-
-
var legacyRadio
-
-

Getter for legacyRadio.

-
- -Expand source code - -
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
-
-
-
var my_node
-
-

Getter for my_node.

-
- -Expand source code - -
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
-
-
-
var no_save
-
-

Getter for no_save.

-
- -Expand source code - -
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)
-
-
-
var node_db
-
-

Getter for node_db.

-
- -Expand source code - -
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
-
-
-
var owner
-
-

Getter for owner.

-
- -Expand source code - -
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
-
-
-
var receive_queue
-
-

Getter for receive_queue.

-
- -Expand source code - -
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
-
-
-
var rx_text_message
-
-

Getter for rx_text_message.

-
- -Expand source code - -
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
-
-
-
var version
-
-

Getter for version.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class LegacyRadioConfig -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var LegacyPreferences
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-
-
var PREFERENCES_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var preferences
-
-

Getter for preferences.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/environmental_measurement_pb2.html b/docs/meshtastic/environmental_measurement_pb2.html deleted file mode 100644 index e12dcf3..0000000 --- a/docs/meshtastic/environmental_measurement_pb2.html +++ /dev/null @@ -1,746 +0,0 @@ - - - - - - -meshtastic.environmental_measurement_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.environmental_measurement_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: environmental_measurement.proto
-
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='environmental_measurement.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\x1f\x65nvironmental_measurement.proto\"g\n\x18\x45nvironmentalMeasurement\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\x19\n\x11relative_humidity\x18\x02 \x01(\x02\x12\x1b\n\x13\x62\x61rometric_pressure\x18\x03 \x01(\x02\x42#Z!github.com/meshtastic/gomeshprotob\x06proto3'
-)
-
-
-
-
-_ENVIRONMENTALMEASUREMENT = _descriptor.Descriptor(
-  name='EnvironmentalMeasurement',
-  full_name='EnvironmentalMeasurement',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='temperature', full_name='EnvironmentalMeasurement.temperature', index=0,
-      number=1, type=2, cpp_type=6, label=1,
-      has_default_value=False, default_value=float(0),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='relative_humidity', full_name='EnvironmentalMeasurement.relative_humidity', index=1,
-      number=2, type=2, cpp_type=6, label=1,
-      has_default_value=False, default_value=float(0),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='barometric_pressure', full_name='EnvironmentalMeasurement.barometric_pressure', index=2,
-      number=3, type=2, cpp_type=6, label=1,
-      has_default_value=False, default_value=float(0),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=35,
-  serialized_end=138,
-)
-
-DESCRIPTOR.message_types_by_name['EnvironmentalMeasurement'] = _ENVIRONMENTALMEASUREMENT
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-EnvironmentalMeasurement = _reflection.GeneratedProtocolMessageType('EnvironmentalMeasurement', (_message.Message,), {
-  'DESCRIPTOR' : _ENVIRONMENTALMEASUREMENT,
-  '__module__' : 'environmental_measurement_pb2'
-  # @@protoc_insertion_point(class_scope:EnvironmentalMeasurement)
-  })
-_sym_db.RegisterMessage(EnvironmentalMeasurement)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class EnvironmentalMeasurement -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var BAROMETRIC_PRESSURE_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
var RELATIVE_HUMIDITY_FIELD_NUMBER
-
-
-
-
var TEMPERATURE_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var barometric_pressure
-
-

Getter for barometric_pressure.

-
- -Expand source code - -
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)
-
-
-
var relative_humidity
-
-

Getter for relative_humidity.

-
- -Expand source code - -
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)
-
-
-
var temperature
-
-

Getter for temperature.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/globals.html b/docs/meshtastic/globals.html deleted file mode 100644 index 9ce2f4b..0000000 --- a/docs/meshtastic/globals.html +++ /dev/null @@ -1,380 +0,0 @@ - - - - - - -meshtastic.globals API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.globals

-
-
-

Globals singleton class.

-

Instead of using a global, stuff your variables in this "trash can". -This is not much better than using python's globals, but it allows -us to better test meshtastic. Plus, there are some weird python -global issues/gotcha that we can hopefully avoid by using this -class instead.

-
- -Expand source code - -
"""Globals singleton class.
-
-   Instead of using a global, stuff your variables in this "trash can".
-   This is not much better than using python's globals, but it allows
-   us to better test meshtastic. Plus, there are some weird python
-   global issues/gotcha that we can hopefully avoid by using this
-   class instead.
-
-"""
-
-class Globals:
-    """Globals class is a Singleton."""
-    __instance = None
-
-    @staticmethod
-    def getInstance():
-        """Get an instance of the Globals class."""
-        if Globals.__instance is None:
-            Globals()
-        return Globals.__instance
-
-    def __init__(self):
-        """Constructor for the Globals CLass"""
-        if Globals.__instance is not None:
-            raise Exception("This class is a singleton")
-        else:
-            Globals.__instance = self
-        self.args = None
-        self.parser = None
-        self.target_node = None
-        self.channel_index = None
-
-    def reset(self):
-        """Reset all of our globals. If you add a member, add it to this method, too."""
-        self.args = None
-        self.parser = None
-        self.target_node = None
-        self.channel_index = None
-
-    def set_args(self, args):
-        """Set the args"""
-        self.args = args
-
-    def set_parser(self, parser):
-        """Set the parser"""
-        self.parser = parser
-
-    def set_target_node(self, target_node):
-        """Set the target_node"""
-        self.target_node = target_node
-
-    def set_channel_index(self, channel_index):
-        """Set the channel_index"""
-        self.channel_index = channel_index
-
-    def get_args(self):
-        """Get args"""
-        return self.args
-
-    def get_parser(self):
-        """Get parser"""
-        return self.parser
-
-    def get_target_node(self):
-        """Get target_node"""
-        return self.target_node
-
-    def get_channel_index(self):
-        """Get channel_index"""
-        return self.channel_index
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Globals -
-
-

Globals class is a Singleton.

-

Constructor for the Globals CLass

-
- -Expand source code - -
class Globals:
-    """Globals class is a Singleton."""
-    __instance = None
-
-    @staticmethod
-    def getInstance():
-        """Get an instance of the Globals class."""
-        if Globals.__instance is None:
-            Globals()
-        return Globals.__instance
-
-    def __init__(self):
-        """Constructor for the Globals CLass"""
-        if Globals.__instance is not None:
-            raise Exception("This class is a singleton")
-        else:
-            Globals.__instance = self
-        self.args = None
-        self.parser = None
-        self.target_node = None
-        self.channel_index = None
-
-    def reset(self):
-        """Reset all of our globals. If you add a member, add it to this method, too."""
-        self.args = None
-        self.parser = None
-        self.target_node = None
-        self.channel_index = None
-
-    def set_args(self, args):
-        """Set the args"""
-        self.args = args
-
-    def set_parser(self, parser):
-        """Set the parser"""
-        self.parser = parser
-
-    def set_target_node(self, target_node):
-        """Set the target_node"""
-        self.target_node = target_node
-
-    def set_channel_index(self, channel_index):
-        """Set the channel_index"""
-        self.channel_index = channel_index
-
-    def get_args(self):
-        """Get args"""
-        return self.args
-
-    def get_parser(self):
-        """Get parser"""
-        return self.parser
-
-    def get_target_node(self):
-        """Get target_node"""
-        return self.target_node
-
-    def get_channel_index(self):
-        """Get channel_index"""
-        return self.channel_index
-
-

Static methods

-
-
-def getInstance() -
-
-

Get an instance of the Globals class.

-
- -Expand source code - -
@staticmethod
-def getInstance():
-    """Get an instance of the Globals class."""
-    if Globals.__instance is None:
-        Globals()
-    return Globals.__instance
-
-
-
-

Methods

-
-
-def get_args(self) -
-
-

Get args

-
- -Expand source code - -
def get_args(self):
-    """Get args"""
-    return self.args
-
-
-
-def get_channel_index(self) -
-
-

Get channel_index

-
- -Expand source code - -
def get_channel_index(self):
-    """Get channel_index"""
-    return self.channel_index
-
-
-
-def get_parser(self) -
-
-

Get parser

-
- -Expand source code - -
def get_parser(self):
-    """Get parser"""
-    return self.parser
-
-
-
-def get_target_node(self) -
-
-

Get target_node

-
- -Expand source code - -
def get_target_node(self):
-    """Get target_node"""
-    return self.target_node
-
-
-
-def reset(self) -
-
-

Reset all of our globals. If you add a member, add it to this method, too.

-
- -Expand source code - -
def reset(self):
-    """Reset all of our globals. If you add a member, add it to this method, too."""
-    self.args = None
-    self.parser = None
-    self.target_node = None
-    self.channel_index = None
-
-
-
-def set_args(self, args) -
-
-

Set the args

-
- -Expand source code - -
def set_args(self, args):
-    """Set the args"""
-    self.args = args
-
-
-
-def set_channel_index(self, channel_index) -
-
-

Set the channel_index

-
- -Expand source code - -
def set_channel_index(self, channel_index):
-    """Set the channel_index"""
-    self.channel_index = channel_index
-
-
-
-def set_parser(self, parser) -
-
-

Set the parser

-
- -Expand source code - -
def set_parser(self, parser):
-    """Set the parser"""
-    self.parser = parser
-
-
-
-def set_target_node(self, target_node) -
-
-

Set the target_node

-
- -Expand source code - -
def set_target_node(self, target_node):
-    """Set the target_node"""
-    self.target_node = target_node
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/index.html b/docs/meshtastic/index.html deleted file mode 100644 index cefec61..0000000 --- a/docs/meshtastic/index.html +++ /dev/null @@ -1,538 +0,0 @@ - - - - - - -meshtastic API documentation - - - - - - - - - - - -
-
-
-

Package meshtastic

-
-
-

an API for Meshtastic devices

-

Primary class: SerialInterface -Install with pip: "pip3 install meshtastic" -Source code on github

-

properties of SerialInterface:

-
    -
  • radioConfig - Current radio configuration and device settings, if you write to this the new settings will be applied to -the device.
  • -
  • nodes - The database of received nodes. -Includes always up-to-date location and username information for each -node in the mesh. -This is a read-only datastructure.
  • -
  • nodesByNum - like "nodes" but keyed by nodeNum instead of nodeId
  • -
  • myInfo - Contains read-only information about the local radio device (software version, hardware version, etc)
  • -
-

Published PubSub topics

-

We use a publish-subscribe model to communicate asynchronous events. -Available -topics:

-
    -
  • meshtastic.connection.established - published once we've successfully connected to the radio and downloaded the node DB
  • -
  • meshtastic.connection.lost - published once we've lost our link to the radio
  • -
  • meshtastic.receive.text(packet) - delivers a received packet as a dictionary, if you only care about a particular -type of packet, you should subscribe to the full topic name. -If you want to see all packets, simply subscribe to "meshtastic.receive".
  • -
  • meshtastic.receive.position(packet)
  • -
  • meshtastic.receive.user(packet)
  • -
  • meshtastic.receive.data.portnum(packet) (where portnum is an integer or well known PortNum enum)
  • -
  • meshtastic.node.updated(node = NodeInfo) - published when a node in the DB changes (appears, location changed, username changed, etc…)
  • -
-

We receive position, user, or data packets from the mesh. -You probably only care about meshtastic.receive.data. -The first argument for -that publish will be the packet. -Text or binary data packets (from sendData or sendText) will both arrive this way. -If you print packet -you'll see the fields in the dictionary. -decoded.data.payload will contain the raw bytes that were sent. -If the packet was sent with -sendText, decoded.data.text will also be populated with the decoded string. -For ASCII these two strings will be the same, but for -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
-    print(f"Received: {packet}")
-
-def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect to the radio
-    # defaults to broadcast, specify a destination ID if you wish
-    interface.sendText("hello mesh")
-
-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.serial_interface.SerialInterface()
-
-
-
- -Expand source code - -
"""
-# an API for Meshtastic devices
-
-Primary class: SerialInterface
-Install with pip: "[pip3 install meshtastic](https://pypi.org/project/meshtastic/)"
-Source code on [github](https://github.com/meshtastic/Meshtastic-python)
-
-properties of SerialInterface:
-
-- radioConfig - Current radio configuration and device settings, if you write to this the new settings will be applied to
-the device.
-- nodes - The database of received nodes.  Includes always up-to-date location and username information for each
-node in the mesh.  This is a read-only datastructure.
-- nodesByNum - like "nodes" but keyed by nodeNum instead of nodeId
-- myInfo - Contains read-only information about the local radio device (software version, hardware version, etc)
-
-# Published PubSub topics
-
-We use a [publish-subscribe](https://pypubsub.readthedocs.io/en/v4.0.3/) model to communicate asynchronous events.  Available
-topics:
-
-- meshtastic.connection.established - published once we've successfully connected to the radio and downloaded the node DB
-- meshtastic.connection.lost - published once we've lost our link to the radio
-- meshtastic.receive.text(packet) - delivers a received packet as a dictionary, if you only care about a particular
-type of packet, you should subscribe to the full topic name.  If you want to see all packets, simply subscribe to "meshtastic.receive".
-- meshtastic.receive.position(packet)
-- meshtastic.receive.user(packet)
-- meshtastic.receive.data.portnum(packet) (where portnum is an integer or well known PortNum enum)
-- meshtastic.node.updated(node = NodeInfo) - published when a node in the DB changes (appears, location changed, username changed, etc...)
-
-We receive position, user, or data packets from the mesh.  You probably only care about meshtastic.receive.data.  The first argument for
-that publish will be the packet.  Text or binary data packets (from sendData or sendText) will both arrive this way.  If you print packet
-you'll see the fields in the dictionary.  decoded.data.payload will contain the raw bytes that were sent.  If the packet was sent with
-sendText, decoded.data.text will **also** be populated with the decoded string.  For ASCII these two strings will be the same, but for
-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
-    print(f"Received: {packet}")
-
-def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect to the radio
-    # defaults to broadcast, specify a destination ID if you wish
-    interface.sendText("hello mesh")
-
-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.serial_interface.SerialInterface()
-
-```
-
-"""
-
-import base64
-import logging
-import os
-import platform
-import random
-import socket
-import sys
-import stat
-import threading
-import traceback
-import time
-from datetime import datetime
-from typing import *
-import serial
-import timeago
-import google.protobuf.json_format
-import pygatt
-from pubsub import pub
-from dotmap import DotMap
-from tabulate import tabulate
-from google.protobuf.json_format import MessageToJson
-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.
-
-LOCAL_ADDR = "^local"
-"""A special ID that means the local node"""
-
-BROADCAST_NUM = 0xffffffff
-"""if using 8 bit nodenums this will be shortend on the target"""
-
-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
-"""
-
-publishingThread = DeferredExecution("publishing")
-
-
-class ResponseHandler(NamedTuple):
-    """A pending response callback, waiting for a response to one of our messages"""
-    # requestId: int - used only as a key
-    callback: Callable
-    # FIXME, add timestamp and age out old requests
-
-
-class KnownProtocol(NamedTuple):
-    """Used to automatically decode known protocol payloads"""
-    name: str
-    # portnum: int, now a key
-    # If set, will be called to prase as a protocol buffer
-    protobufFactory: Callable = None
-    # If set, invoked as onReceive(interface, packet)
-    onReceive: Callable = None
-
-
-def _onTextReceive(iface, asDict):
-    """Special text auto parsing for received messages"""
-    # We don't throw if the utf8 is invalid in the text message.  Instead we just don't populate
-    # the decoded.data.text and we log an error message.  This at least allows some delivery to
-    # the app and the app can deal with the missing decoded representation.
-    #
-    # Usually btw this problem is caused by apps sending binary data but setting the payload type to
-    # text.
-    try:
-        asBytes = asDict["decoded"]["payload"]
-        asDict["decoded"]["text"] = asBytes.decode("utf-8")
-    except Exception as ex:
-        logging.error(f"Malformatted utf8 in text message: {ex}")
-    _receiveInfoUpdate(iface, asDict)
-
-
-def _onPositionReceive(iface, asDict):
-    """Special auto parsing for received messages"""
-    p = asDict["decoded"]["position"]
-    iface._fixupPosition(p)
-    # update node DB as needed
-    iface._getOrCreateByNum(asDict["from"])["position"] = p
-
-
-def _onNodeInfoReceive(iface, asDict):
-    """Special auto parsing for received messages"""
-    p = asDict["decoded"]["user"]
-    # decode user protobufs and update nodedb, provide decoded version as "position" in the published msg
-    # update node DB as needed
-    n = iface._getOrCreateByNum(asDict["from"])
-    n["user"] = p
-    # We now have a node ID, make sure it is uptodate in that table
-    iface.nodes[p["id"]] = n
-    _receiveInfoUpdate(iface, asDict)
-
-
-def _receiveInfoUpdate(iface, asDict):
-    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"""
-protocols = {
-    portnums_pb2.PortNum.TEXT_MESSAGE_APP: KnownProtocol("text", onReceive=_onTextReceive),
-    portnums_pb2.PortNum.POSITION_APP: KnownProtocol("position", mesh_pb2.Position, _onPositionReceive),
-    portnums_pb2.PortNum.NODEINFO_APP: KnownProtocol("user", mesh_pb2.User, _onNodeInfoReceive),
-    portnums_pb2.PortNum.ADMIN_APP: KnownProtocol("admin", admin_pb2.AdminMessage),
-    portnums_pb2.PortNum.ROUTING_APP: KnownProtocol("routing", mesh_pb2.Routing),
-    portnums_pb2.PortNum.ENVIRONMENTAL_MEASUREMENT_APP: KnownProtocol("environmental", environmental_measurement_pb2.EnvironmentalMeasurement),
-    portnums_pb2.PortNum.REMOTE_HARDWARE_APP: KnownProtocol(
-        "remotehw", remote_hardware_pb2.HardwareMessage)
-}
-
-
-
-

Sub-modules

-
-
meshtastic.admin_pb2
-
-
-
-
meshtastic.apponly_pb2
-
-
-
-
meshtastic.ble
-
-
-
-
meshtastic.ble_interface
-
-

Bluetooth interface

-
-
meshtastic.channel_pb2
-
-
-
-
meshtastic.deviceonly_pb2
-
-
-
-
meshtastic.environmental_measurement_pb2
-
-
-
-
meshtastic.globals
-
-

Globals singleton class …

-
-
meshtastic.mesh_interface
-
-

Mesh Interface class

-
-
meshtastic.mesh_pb2
-
-
-
-
meshtastic.mqtt_pb2
-
-
-
-
meshtastic.node
-
-

Node class

-
-
meshtastic.portnums_pb2
-
-
-
-
meshtastic.radioconfig_pb2
-
-
-
-
meshtastic.remote_hardware
-
-

Remote hardware

-
-
meshtastic.remote_hardware_pb2
-
-
-
-
meshtastic.serial_interface
-
-

Serial interface class

-
-
meshtastic.storeforward_pb2
-
-
-
-
meshtastic.stream_interface
-
-

Stream Interface base class

-
-
meshtastic.tcp_interface
-
-

TCPInterface class for interfacing with http endpoint

-
-
meshtastic.test
-
-

With two radios connected serially, send and receive test -messages and report back if successful.

-
-
meshtastic.tests
-
-
-
-
meshtastic.tunnel
-
-

Code for IP tunnel over a mesh …

-
-
meshtastic.util
-
-

Utility functions.

-
-
-
-
-

Global variables

-
-
var BROADCAST_ADDR
-
-

A special ID that means broadcast

-
-
var BROADCAST_NUM
-
-

if using 8 bit nodenums this will be shortend on the target

-
-
var LOCAL_ADDR
-
-

A special ID that means the local node

-
-
var OUR_APP_VERSION
-
-

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

-
-
-
-
-
-
-

Classes

-
-
-class KnownProtocol -(name: str, protobufFactory: Callable = None, onReceive: Callable = None) -
-
-

Used to automatically decode known protocol payloads

-
- -Expand source code - -
class KnownProtocol(NamedTuple):
-    """Used to automatically decode known protocol payloads"""
-    name: str
-    # portnum: int, now a key
-    # If set, will be called to prase as a protocol buffer
-    protobufFactory: Callable = None
-    # If set, invoked as onReceive(interface, packet)
-    onReceive: Callable = None
-
-

Ancestors

-
    -
  • builtins.tuple
  • -
-

Instance variables

-
-
var name : str
-
-

Alias for field number 0

-
-
var onReceive : Callable
-
-

Alias for field number 2

-
-
var protobufFactory : Callable
-
-

Alias for field number 1

-
-
-
-
-class ResponseHandler -(callback: Callable) -
-
-

A pending response callback, waiting for a response to one of our messages

-
- -Expand source code - -
class ResponseHandler(NamedTuple):
-    """A pending response callback, waiting for a response to one of our messages"""
-    # requestId: int - used only as a key
-    callback: Callable
-    # FIXME, add timestamp and age out old requests
-
-

Ancestors

-
    -
  • builtins.tuple
  • -
-

Instance variables

-
-
var callback : Callable
-
-

Alias for field number 0

-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/mesh_interface.html b/docs/meshtastic/mesh_interface.html deleted file mode 100644 index 0dcc735..0000000 --- a/docs/meshtastic/mesh_interface.html +++ /dev/null @@ -1,1851 +0,0 @@ - - - - - - -meshtastic.mesh_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.mesh_interface

-
-
-

Mesh Interface class

-
- -Expand source code - -
"""Mesh Interface class
-"""
-import sys
-import random
-import time
-import logging
-from typing import AnyStr
-import threading
-from datetime import datetime
-import timeago
-from tabulate import tabulate
-
-import google.protobuf.json_format
-
-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 .__init__ import LOCAL_ADDR, BROADCAST_NUM, BROADCAST_ADDR, ResponseHandler, publishingThread, OUR_APP_VERSION, protocols
-
-class MeshInterface:
-    """Interface class for meshtastic devices
-
-    Properties:
-
-    isConnected
-    nodes
-    debugOut
-    """
-
-    def __init__(self, debugOut=None, noProto=False):
-        """Constructor
-
-        Keyword Arguments:
-            noProto -- If True, don't try to run our protocol on the
-                       link - just be a dumb serial client.
-        """
-        self.debugOut = debugOut
-        self.nodes = None  # FIXME
-        self.isConnected = threading.Event()
-        self.noProto = noProto
-        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
-        self._timeout = Timeout()
-        self.heartbeatTimer = None
-        random.seed()  # FIXME, we should not clobber the random seedval here, instead tell user they must call it
-        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"""
-        if self.heartbeatTimer:
-            self.heartbeatTimer.cancel()
-
-        self._sendDisconnect()
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, exc_type, exc_value, traceback):
-        if exc_type is not None and exc_value is not None:
-            logging.error(
-                f'An exception of type {exc_type} with value {exc_value} has occurred')
-        if traceback is not None:
-            logging.error(f'Traceback: {traceback}')
-        self.close()
-
-    def showInfo(self, file=sys.stdout):
-        """Show human readable summary about this object"""
-        owner = f"Owner: {self.getLongName()} ({self.getShortName()})"
-        myinfo = ''
-        if self.myInfo:
-            myinfo = f"\nMy info: {stripnl(MessageToJson(self.myInfo))}"
-        mesh = "\nNodes in mesh:"
-        nodes = ""
-        if self.nodes:
-            for n in self.nodes.values():
-                nodes = nodes + f"  {stripnl(n)}"
-        infos = owner + myinfo + mesh + nodes
-        print(infos)
-        return infos
-
-    def showNodes(self, includeSelf=True, file=sys.stdout):
-        """Show table summary of nodes in mesh"""
-        def formatFloat(value, precision=2, unit=''):
-            """Format a float value with precsion."""
-            return f'{value:.{precision}f}{unit}' if value else None
-
-        def getLH(ts):
-            """Format last heard"""
-            return datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') if ts else None
-
-        def getTimeAgo(ts):
-            """Format how long ago have we heard from this node (aka timeago)."""
-            return timeago.format(datetime.fromtimestamp(ts), datetime.now()) if ts else None
-
-        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
-
-                row = {"N": 0}
-
-                user = node.get('user')
-                if user:
-                    row.update({
-                        "User": user['longName'],
-                        "AKA":  user['shortName'],
-                        "ID":   user['id'],
-                    })
-
-                pos = node.get('position')
-                if pos:
-                    row.update({
-                        "Latitude":  formatFloat(pos.get("latitude"),     4, "°"),
-                        "Longitude": formatFloat(pos.get("longitude"),    4, "°"),
-                        "Altitude":  formatFloat(pos.get("altitude"),     0, " m"),
-                        "Battery":   formatFloat(pos.get("batteryLevel"), 2, "%"),
-                    })
-
-                row.update({
-                    "SNR":       formatFloat(node.get("snr"), 2, " dB"),
-                    "LastHeard": getLH(node.get("lastHeard")),
-                    "Since":     getTimeAgo(node.get("lastHeard")),
-                })
-
-                rows.append(row)
-
-        rows.sort(key=lambda r: r.get('LastHeard') or '0000', reverse=True)
-        for i, row in enumerate(rows):
-            row['N'] = i+1
-
-        table = tabulate(rows, headers='keys', missingval='N/A', tablefmt='fancy_grid')
-        print(table)
-        return table
-
-
-    def getNode(self, nodeId):
-        """Return a node object which contains device settings and channel info"""
-        if nodeId == LOCAL_ADDR:
-            return self.localNode
-        else:
-            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")
-            return n
-
-    def sendText(self, text: AnyStr,
-                 destinationId=BROADCAST_ADDR,
-                 wantAck=False,
-                 wantResponse=False,
-                 hopLimit=None,
-                 onResponse=None,
-                 channelIndex=0):
-        """Send a utf8 string to some other node, if the node has a display it
-           will also be shown on the device.
-
-        Arguments:
-            text {string} -- The text to send
-
-        Keyword Arguments:
-            destinationId {nodeId or nodeNum} -- where to send this
-                                                 message (default: {BROADCAST_ADDR})
-            portNum -- the application portnum (similar to IP port numbers)
-                       of the destination, see portnums.proto for a list
-            wantAck -- True if you want the message sent in a reliable manner
-                       (with retries and ack/nak provided for delivery)
-            wantResponse -- True if you want the service on the other side to
-                            send an application layer response
-
-        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,
-                             wantResponse=wantResponse,
-                             hopLimit=hopLimit,
-                             onResponse=onResponse,
-                             channelIndex=channelIndex)
-
-    def sendData(self, data, destinationId=BROADCAST_ADDR,
-                 portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
-                 wantResponse=False,
-                 hopLimit=None,
-                 onResponse=None,
-                 channelIndex=0):
-        """Send a data packet to some other node
-
-        Keyword Arguments:
-            data -- the data to send, either as an array of bytes or
-                    as a protobuf (which will be automatically
-                    serialized to bytes)
-            destinationId {nodeId or nodeNum} -- where to send this
-                    message (default: {BROADCAST_ADDR})
-            portNum -- the application portnum (similar to IP port numbers)
-                    of the destination, see portnums.proto for a list
-            wantAck -- True if you want the message sent in a reliable
-                    manner (with retries and ack/nak provided for delivery)
-            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)
-            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:
-            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")
-
-        meshPacket = mesh_pb2.MeshPacket()
-        meshPacket.channel = channelIndex
-        meshPacket.decoded.payload = data
-        meshPacket.decoded.portnum = portNum
-        meshPacket.decoded.want_response = wantResponse
-
-        p = self._sendPacket(meshPacket, destinationId,
-                             wantAck=wantAck, hopLimit=hopLimit)
-        if onResponse is not None:
-            self._addResponseHandler(p.id, onResponse)
-        return p
-
-    def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0,
-                     destinationId=BROADCAST_ADDR, wantAck=False, wantResponse=False):
-        """
-        Send a position packet to some other node (normally a broadcast)
-
-        Also, the device software will notice this packet and use it to automatically
-        set its notion of the local position.
-
-        If timeSec is not specified (recommended), we will use the local machine time.
-
-        Returns the sent packet. The id field will be populated in this packet and
-        can be used to track future message acks/naks.
-        """
-        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,
-                             wantAck=wantAck,
-                             wantResponse=wantResponse)
-
-    def _addResponseHandler(self, requestId, callback):
-        self.responseHandlers[requestId] = ResponseHandler(callback)
-
-    def _sendPacket(self, meshPacket,
-                    destinationId=BROADCAST_ADDR,
-                    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):
-            self._waitConnected()
-
-        toRadio = mesh_pb2.ToRadio()
-
-        nodeNum = 0
-        if destinationId is None:
-            our_exit("Warning: destinationId must not be None")
-        elif isinstance(destinationId, int):
-            nodeNum = destinationId
-        elif destinationId == BROADCAST_ADDR:
-            nodeNum = BROADCAST_NUM
-        elif destinationId == LOCAL_ADDR:
-            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:
-            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
-        meshPacket.hop_limit = hopLimit
-
-        # if the user hasn't set an ID for this packet (likely and recommended),
-        # we should pick a new unique ID so the message can be tracked.
-        if meshPacket.id == 0:
-            meshPacket.id = self._generatePacketId()
-
-        toRadio.packet.CopyFrom(meshPacket)
-        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):
-        """Block until radio config is received. Returns True if config has been received."""
-        success = self._timeout.waitForSet(self, attrs=('myInfo', 'nodes')) and self.localNode.waitForConfig()
-        if not success:
-            raise Exception("Timed out waiting for interface config")
-
-    def getMyNodeInfo(self):
-        """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):
-        """Get user"""
-        nodeInfo = self.getMyNodeInfo()
-        if nodeInfo is not None:
-            return nodeInfo.get('user')
-        return None
-
-    def getLongName(self):
-        """Get long name"""
-        user = self.getMyUser()
-        if user is not None:
-            return user.get('longName', None)
-        return None
-
-    def getShortName(self):
-        """Get short name"""
-        user = self.getMyUser()
-        if user is not None:
-            return user.get('shortName', None)
-        return None
-
-    def _waitConnected(self):
-        """Block until the initial node db download is complete, or timeout
-        and raise an exception"""
-        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:
-            raise self.failure
-
-    def _generatePacketId(self):
-        """Get a new unique packet ID"""
-        if self.currentPacketId is None:
-            raise Exception("Not connected yet, can not generate packet")
-        else:
-            self.currentPacketId = (self.currentPacketId + 1) & 0xffffffff
-            return self.currentPacketId
-
-    def _disconnected(self):
-        """Called by subclasses to tell clients this interface has disconnected"""
-        self.isConnected.clear()
-        publishingThread.queueWork(lambda: pub.sendMessage(
-            "meshtastic.connection.lost", interface=self))
-
-    def _startHeartbeat(self):
-        """We need to send a heartbeat message to the device every X seconds"""
-        def callback():
-            self.heartbeatTimer = None
-            prefs = self.localNode.radioConfig.preferences
-            i = prefs.phone_timeout_secs / 2
-            logging.debug(f"Sending heartbeat, interval {i}")
-            if i != 0:
-                self.heartbeatTimer = threading.Timer(i, callback)
-                self.heartbeatTimer.start()
-                p = mesh_pb2.ToRadio()
-                self._sendToRadio(p)
-
-        callback()  # run our periodic callback now, it will make another timer if necessary
-
-    def _connected(self):
-        """Called by this class to tell clients we are now fully connected to a node
-        """
-        # (because I'm lazy) _connected might be called when remote Node
-        # objects complete their config reads, don't generate redundant isConnected
-        # for the local interface
-        if not self.isConnected.is_set():
-            self.isConnected.set()
-            self._startHeartbeat()
-            publishingThread.queueWork(lambda: pub.sendMessage(
-                "meshtastic.connection.established", interface=self))
-
-    def _startConfig(self):
-        """Start device packets flowing"""
-        self.myInfo = None
-        self.nodes = {}  # nodes keyed by ID
-        self.nodesByNum = {}  # nodes keyed by nodenum
-
-        startConfig = mesh_pb2.ToRadio()
-        self.configId = random.randint(0, 0xffffffff)
-        startConfig.want_config_id = self.configId
-        self._sendToRadio(startConfig)
-
-    def _sendDisconnect(self):
-        """Tell device we are done using it"""
-        m = mesh_pb2.ToRadio()
-        m.disconnect = True
-        self._sendToRadio(m)
-
-    def _sendToRadio(self, toRadio):
-        """Send a ToRadio protobuf to the device"""
-        if self.noProto:
-            logging.warning(f"Not sending packet because protocol use is disabled by noProto")
-        else:
-            #logging.debug(f"Sending toRadio: {stripnl(toRadio)}")
-            self._sendToRadioImpl(toRadio)
-
-    def _sendToRadioImpl(self, toRadio):
-        """Send a ToRadio protobuf to the device"""
-        logging.error(f"Subclass must provide toradio: {toRadio}")
-
-    def _handleConfigComplete(self):
-        """
-        Done with initial config messages, now send regular MeshPackets
-        to ask for settings and channels
-        """
-        self.localNode.requestConfig()
-
-    def _handleFromRadio(self, fromRadioBytes):
-        """
-        Handle a packet that arrived from the radio(update model and publish events)
-
-        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}")
-        if fromRadio.HasField("my_info"):
-            self.myInfo = fromRadio.my_info
-            self.localNode.nodeNum = self.myInfo.my_node_num
-            logging.debug(f"Received myinfo: {stripnl(fromRadio.my_info)}")
-
-            failmsg = None
-            # Check for app too old
-            if self.myInfo.min_app_version > OUR_APP_VERSION:
-                failmsg = "This device needs a newer python client, run 'pip install --upgrade meshtastic'."\
-                          "For more information see https://tinyurl.com/5bjsxu32"
-
-            # check for firmware too old
-            if self.myInfo.max_channels == 0:
-                failmsg = "This version of meshtastic-python requires device firmware version 1.2 or later. "\
-                          "For more information see https://tinyurl.com/5bjsxu32"
-
-            if failmsg:
-                self.failure = Exception(failmsg)
-                self.isConnected.set()  # let waitConnected return this exception
-                self.close()
-
-        elif fromRadio.HasField("node_info"):
-            node = asDict["nodeInfo"]
-            try:
-                self._fixupPosition(node["position"])
-            except:
-                logging.debug("Node without position")
-
-            logging.debug(f"Received nodeinfo: {node}")
-
-            self.nodesByNum[node["num"]] = node
-            if "user" in node:  # Some nodes might not have user/ids assigned yet
-                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:
-            # we ignore the config_complete_id, it is unneeded for our
-            # stream API fromRadio.config_complete_id
-            logging.debug(f"Config complete ID {self.configId}")
-            self._handleConfigComplete()
-        elif fromRadio.HasField("packet"):
-            self._handlePacketFromRadio(fromRadio.packet)
-        elif fromRadio.rebooted:
-            # Tell clients the device went away.  Careful not to call the overridden
-            # subclass version that closes the serial port
-            MeshInterface._disconnected(self)
-
-            self._startConfig()  # redownload the node db etc...
-        else:
-            logging.debug("Unexpected FromRadio payload")
-
-    def _fixupPosition(self, position):
-        """Convert integer lat/lon into floats
-
-        Arguments:
-            position {Position dictionary} -- object ot fix up
-        """
-        if "latitudeI" in position:
-            position["latitude"] = position["latitudeI"] * 1e-7
-        if "longitudeI" in position:
-            position["longitude"] = position["longitudeI"] * 1e-7
-
-    def _nodeNumToId(self, num):
-        """Map a node node number to a node ID
-
-        Arguments:
-            num {int} -- Node number
-
-        Returns:
-            string -- Node ID
-        """
-        if num == BROADCAST_NUM:
-            return BROADCAST_ADDR
-
-        try:
-            return self.nodesByNum[num]["user"]["id"]
-        except:
-            logging.debug(f"Node {num} not found for fromId")
-            return None
-
-    def _getOrCreateByNum(self, nodeNum):
-        """Given a nodenum find the NodeInfo in the DB (or create if necessary)"""
-        if nodeNum == BROADCAST_NUM:
-            raise Exception("Can not create/find nodenum by the broadcast num")
-
-        if nodeNum in self.nodesByNum:
-            return self.nodesByNum[nodeNum]
-        else:
-            n = {"num": nodeNum}  # Create a minimial node db entry
-            self.nodesByNum[nodeNum] = n
-            return n
-
-    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
-        # doesn't need to understand protobufs.  But advanced clients might
-        # want the raw protobuf, so we provide it in "raw"
-        asDict["raw"] = meshPacket
-
-        # from might be missing if the nodenum was zero.
-        if not hack and "from" not in asDict:
-            asDict["from"] = 0
-            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
-
-        # /add fromId and toId fields based on the node ID
-        try:
-            asDict["fromId"] = self._nodeNumToId(asDict["from"])
-        except Exception as ex:
-            logging.warning(f"Not populating fromId {ex}")
-        try:
-            asDict["toId"] = self._nodeNumToId(asDict["to"])
-        except Exception as ex:
-            logging.warning(f"Not populating toId {ex}")
-
-        # We could provide our objects as DotMaps - which work with . notation or as dictionaries
-        # asObj = DotMap(asDict)
-        topic = "meshtastic.receive"  # Generic unknown packet type
-
-        decoded = asDict["decoded"]
-        # The default MessageToDict converts byte arrays into base64 strings.
-        # We don't want that - it messes up data payload.  So slam in the correct
-        # byte array.
-        decoded["payload"] = meshPacket.decoded.payload
-
-        # 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 "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"]
-
-        topic = f"meshtastic.receive.data.{portnum}"
-
-        # decode position protobufs and update nodedb, provide decoded version
-        # as "position" in the published msg move the following into a 'decoders'
-        # API that clients could register?
-        portNumInt = meshPacket.decoded.portnum  # we want portnum as an int
-        handler = protocols.get(portNumInt)
-        # The decoded protobuf as a dictionary (if we understand this message)
-        p = None
-        if handler is not None:
-            topic = f"meshtastic.receive.{handler.name}"
-
-            # Convert to protobuf if possible
-            if handler.protobufFactory is not None:
-                pb = handler.protobufFactory()
-                pb.ParseFromString(meshPacket.decoded.payload)
-                p = google.protobuf.json_format.MessageToDict(pb)
-                asDict["decoded"][handler.name] = p
-                # Also provide the protobuf raw
-                asDict["decoded"][handler.name]["raw"] = pb
-
-            # Call specialized onReceive if necessary
-            if handler.onReceive is not None:
-                handler.onReceive(self, asDict)
-
-        # Is this message in response to a request, if so, look for a handler
-        requestId = decoded.get("requestId")
-        if requestId is not None:
-            # We ignore ACK packets, but send NAKs and data responses to the handlers
-            routing = decoded.get("routing")
-            isAck = routing is not None and ("errorReason" not in routing)
-            if not isAck:
-                # we keep the responseHandler in dict until we get a non ack
-                handler = self.responseHandlers.pop(requestId, None)
-                if handler is not None:
-                    handler.callback(asDict)
-
-        logging.debug(f"Publishing {topic}: packet={stripnl(asDict)} ")
-        publishingThread.queueWork(lambda: pub.sendMessage(
-            topic, packet=asDict, interface=self))
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class MeshInterface -(debugOut=None, noProto=False) -
-
-

Interface class for meshtastic devices

-

Properties:

-

isConnected -nodes -debugOut

-

Constructor

-

Keyword Arguments: -noProto – If True, don't try to run our protocol on the -link - just be a dumb serial client.

-
- -Expand source code - -
class MeshInterface:
-    """Interface class for meshtastic devices
-
-    Properties:
-
-    isConnected
-    nodes
-    debugOut
-    """
-
-    def __init__(self, debugOut=None, noProto=False):
-        """Constructor
-
-        Keyword Arguments:
-            noProto -- If True, don't try to run our protocol on the
-                       link - just be a dumb serial client.
-        """
-        self.debugOut = debugOut
-        self.nodes = None  # FIXME
-        self.isConnected = threading.Event()
-        self.noProto = noProto
-        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
-        self._timeout = Timeout()
-        self.heartbeatTimer = None
-        random.seed()  # FIXME, we should not clobber the random seedval here, instead tell user they must call it
-        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"""
-        if self.heartbeatTimer:
-            self.heartbeatTimer.cancel()
-
-        self._sendDisconnect()
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, exc_type, exc_value, traceback):
-        if exc_type is not None and exc_value is not None:
-            logging.error(
-                f'An exception of type {exc_type} with value {exc_value} has occurred')
-        if traceback is not None:
-            logging.error(f'Traceback: {traceback}')
-        self.close()
-
-    def showInfo(self, file=sys.stdout):
-        """Show human readable summary about this object"""
-        owner = f"Owner: {self.getLongName()} ({self.getShortName()})"
-        myinfo = ''
-        if self.myInfo:
-            myinfo = f"\nMy info: {stripnl(MessageToJson(self.myInfo))}"
-        mesh = "\nNodes in mesh:"
-        nodes = ""
-        if self.nodes:
-            for n in self.nodes.values():
-                nodes = nodes + f"  {stripnl(n)}"
-        infos = owner + myinfo + mesh + nodes
-        print(infos)
-        return infos
-
-    def showNodes(self, includeSelf=True, file=sys.stdout):
-        """Show table summary of nodes in mesh"""
-        def formatFloat(value, precision=2, unit=''):
-            """Format a float value with precsion."""
-            return f'{value:.{precision}f}{unit}' if value else None
-
-        def getLH(ts):
-            """Format last heard"""
-            return datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') if ts else None
-
-        def getTimeAgo(ts):
-            """Format how long ago have we heard from this node (aka timeago)."""
-            return timeago.format(datetime.fromtimestamp(ts), datetime.now()) if ts else None
-
-        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
-
-                row = {"N": 0}
-
-                user = node.get('user')
-                if user:
-                    row.update({
-                        "User": user['longName'],
-                        "AKA":  user['shortName'],
-                        "ID":   user['id'],
-                    })
-
-                pos = node.get('position')
-                if pos:
-                    row.update({
-                        "Latitude":  formatFloat(pos.get("latitude"),     4, "°"),
-                        "Longitude": formatFloat(pos.get("longitude"),    4, "°"),
-                        "Altitude":  formatFloat(pos.get("altitude"),     0, " m"),
-                        "Battery":   formatFloat(pos.get("batteryLevel"), 2, "%"),
-                    })
-
-                row.update({
-                    "SNR":       formatFloat(node.get("snr"), 2, " dB"),
-                    "LastHeard": getLH(node.get("lastHeard")),
-                    "Since":     getTimeAgo(node.get("lastHeard")),
-                })
-
-                rows.append(row)
-
-        rows.sort(key=lambda r: r.get('LastHeard') or '0000', reverse=True)
-        for i, row in enumerate(rows):
-            row['N'] = i+1
-
-        table = tabulate(rows, headers='keys', missingval='N/A', tablefmt='fancy_grid')
-        print(table)
-        return table
-
-
-    def getNode(self, nodeId):
-        """Return a node object which contains device settings and channel info"""
-        if nodeId == LOCAL_ADDR:
-            return self.localNode
-        else:
-            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")
-            return n
-
-    def sendText(self, text: AnyStr,
-                 destinationId=BROADCAST_ADDR,
-                 wantAck=False,
-                 wantResponse=False,
-                 hopLimit=None,
-                 onResponse=None,
-                 channelIndex=0):
-        """Send a utf8 string to some other node, if the node has a display it
-           will also be shown on the device.
-
-        Arguments:
-            text {string} -- The text to send
-
-        Keyword Arguments:
-            destinationId {nodeId or nodeNum} -- where to send this
-                                                 message (default: {BROADCAST_ADDR})
-            portNum -- the application portnum (similar to IP port numbers)
-                       of the destination, see portnums.proto for a list
-            wantAck -- True if you want the message sent in a reliable manner
-                       (with retries and ack/nak provided for delivery)
-            wantResponse -- True if you want the service on the other side to
-                            send an application layer response
-
-        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,
-                             wantResponse=wantResponse,
-                             hopLimit=hopLimit,
-                             onResponse=onResponse,
-                             channelIndex=channelIndex)
-
-    def sendData(self, data, destinationId=BROADCAST_ADDR,
-                 portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
-                 wantResponse=False,
-                 hopLimit=None,
-                 onResponse=None,
-                 channelIndex=0):
-        """Send a data packet to some other node
-
-        Keyword Arguments:
-            data -- the data to send, either as an array of bytes or
-                    as a protobuf (which will be automatically
-                    serialized to bytes)
-            destinationId {nodeId or nodeNum} -- where to send this
-                    message (default: {BROADCAST_ADDR})
-            portNum -- the application portnum (similar to IP port numbers)
-                    of the destination, see portnums.proto for a list
-            wantAck -- True if you want the message sent in a reliable
-                    manner (with retries and ack/nak provided for delivery)
-            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)
-            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:
-            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")
-
-        meshPacket = mesh_pb2.MeshPacket()
-        meshPacket.channel = channelIndex
-        meshPacket.decoded.payload = data
-        meshPacket.decoded.portnum = portNum
-        meshPacket.decoded.want_response = wantResponse
-
-        p = self._sendPacket(meshPacket, destinationId,
-                             wantAck=wantAck, hopLimit=hopLimit)
-        if onResponse is not None:
-            self._addResponseHandler(p.id, onResponse)
-        return p
-
-    def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0,
-                     destinationId=BROADCAST_ADDR, wantAck=False, wantResponse=False):
-        """
-        Send a position packet to some other node (normally a broadcast)
-
-        Also, the device software will notice this packet and use it to automatically
-        set its notion of the local position.
-
-        If timeSec is not specified (recommended), we will use the local machine time.
-
-        Returns the sent packet. The id field will be populated in this packet and
-        can be used to track future message acks/naks.
-        """
-        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,
-                             wantAck=wantAck,
-                             wantResponse=wantResponse)
-
-    def _addResponseHandler(self, requestId, callback):
-        self.responseHandlers[requestId] = ResponseHandler(callback)
-
-    def _sendPacket(self, meshPacket,
-                    destinationId=BROADCAST_ADDR,
-                    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):
-            self._waitConnected()
-
-        toRadio = mesh_pb2.ToRadio()
-
-        nodeNum = 0
-        if destinationId is None:
-            our_exit("Warning: destinationId must not be None")
-        elif isinstance(destinationId, int):
-            nodeNum = destinationId
-        elif destinationId == BROADCAST_ADDR:
-            nodeNum = BROADCAST_NUM
-        elif destinationId == LOCAL_ADDR:
-            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:
-            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
-        meshPacket.hop_limit = hopLimit
-
-        # if the user hasn't set an ID for this packet (likely and recommended),
-        # we should pick a new unique ID so the message can be tracked.
-        if meshPacket.id == 0:
-            meshPacket.id = self._generatePacketId()
-
-        toRadio.packet.CopyFrom(meshPacket)
-        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):
-        """Block until radio config is received. Returns True if config has been received."""
-        success = self._timeout.waitForSet(self, attrs=('myInfo', 'nodes')) and self.localNode.waitForConfig()
-        if not success:
-            raise Exception("Timed out waiting for interface config")
-
-    def getMyNodeInfo(self):
-        """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):
-        """Get user"""
-        nodeInfo = self.getMyNodeInfo()
-        if nodeInfo is not None:
-            return nodeInfo.get('user')
-        return None
-
-    def getLongName(self):
-        """Get long name"""
-        user = self.getMyUser()
-        if user is not None:
-            return user.get('longName', None)
-        return None
-
-    def getShortName(self):
-        """Get short name"""
-        user = self.getMyUser()
-        if user is not None:
-            return user.get('shortName', None)
-        return None
-
-    def _waitConnected(self):
-        """Block until the initial node db download is complete, or timeout
-        and raise an exception"""
-        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:
-            raise self.failure
-
-    def _generatePacketId(self):
-        """Get a new unique packet ID"""
-        if self.currentPacketId is None:
-            raise Exception("Not connected yet, can not generate packet")
-        else:
-            self.currentPacketId = (self.currentPacketId + 1) & 0xffffffff
-            return self.currentPacketId
-
-    def _disconnected(self):
-        """Called by subclasses to tell clients this interface has disconnected"""
-        self.isConnected.clear()
-        publishingThread.queueWork(lambda: pub.sendMessage(
-            "meshtastic.connection.lost", interface=self))
-
-    def _startHeartbeat(self):
-        """We need to send a heartbeat message to the device every X seconds"""
-        def callback():
-            self.heartbeatTimer = None
-            prefs = self.localNode.radioConfig.preferences
-            i = prefs.phone_timeout_secs / 2
-            logging.debug(f"Sending heartbeat, interval {i}")
-            if i != 0:
-                self.heartbeatTimer = threading.Timer(i, callback)
-                self.heartbeatTimer.start()
-                p = mesh_pb2.ToRadio()
-                self._sendToRadio(p)
-
-        callback()  # run our periodic callback now, it will make another timer if necessary
-
-    def _connected(self):
-        """Called by this class to tell clients we are now fully connected to a node
-        """
-        # (because I'm lazy) _connected might be called when remote Node
-        # objects complete their config reads, don't generate redundant isConnected
-        # for the local interface
-        if not self.isConnected.is_set():
-            self.isConnected.set()
-            self._startHeartbeat()
-            publishingThread.queueWork(lambda: pub.sendMessage(
-                "meshtastic.connection.established", interface=self))
-
-    def _startConfig(self):
-        """Start device packets flowing"""
-        self.myInfo = None
-        self.nodes = {}  # nodes keyed by ID
-        self.nodesByNum = {}  # nodes keyed by nodenum
-
-        startConfig = mesh_pb2.ToRadio()
-        self.configId = random.randint(0, 0xffffffff)
-        startConfig.want_config_id = self.configId
-        self._sendToRadio(startConfig)
-
-    def _sendDisconnect(self):
-        """Tell device we are done using it"""
-        m = mesh_pb2.ToRadio()
-        m.disconnect = True
-        self._sendToRadio(m)
-
-    def _sendToRadio(self, toRadio):
-        """Send a ToRadio protobuf to the device"""
-        if self.noProto:
-            logging.warning(f"Not sending packet because protocol use is disabled by noProto")
-        else:
-            #logging.debug(f"Sending toRadio: {stripnl(toRadio)}")
-            self._sendToRadioImpl(toRadio)
-
-    def _sendToRadioImpl(self, toRadio):
-        """Send a ToRadio protobuf to the device"""
-        logging.error(f"Subclass must provide toradio: {toRadio}")
-
-    def _handleConfigComplete(self):
-        """
-        Done with initial config messages, now send regular MeshPackets
-        to ask for settings and channels
-        """
-        self.localNode.requestConfig()
-
-    def _handleFromRadio(self, fromRadioBytes):
-        """
-        Handle a packet that arrived from the radio(update model and publish events)
-
-        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}")
-        if fromRadio.HasField("my_info"):
-            self.myInfo = fromRadio.my_info
-            self.localNode.nodeNum = self.myInfo.my_node_num
-            logging.debug(f"Received myinfo: {stripnl(fromRadio.my_info)}")
-
-            failmsg = None
-            # Check for app too old
-            if self.myInfo.min_app_version > OUR_APP_VERSION:
-                failmsg = "This device needs a newer python client, run 'pip install --upgrade meshtastic'."\
-                          "For more information see https://tinyurl.com/5bjsxu32"
-
-            # check for firmware too old
-            if self.myInfo.max_channels == 0:
-                failmsg = "This version of meshtastic-python requires device firmware version 1.2 or later. "\
-                          "For more information see https://tinyurl.com/5bjsxu32"
-
-            if failmsg:
-                self.failure = Exception(failmsg)
-                self.isConnected.set()  # let waitConnected return this exception
-                self.close()
-
-        elif fromRadio.HasField("node_info"):
-            node = asDict["nodeInfo"]
-            try:
-                self._fixupPosition(node["position"])
-            except:
-                logging.debug("Node without position")
-
-            logging.debug(f"Received nodeinfo: {node}")
-
-            self.nodesByNum[node["num"]] = node
-            if "user" in node:  # Some nodes might not have user/ids assigned yet
-                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:
-            # we ignore the config_complete_id, it is unneeded for our
-            # stream API fromRadio.config_complete_id
-            logging.debug(f"Config complete ID {self.configId}")
-            self._handleConfigComplete()
-        elif fromRadio.HasField("packet"):
-            self._handlePacketFromRadio(fromRadio.packet)
-        elif fromRadio.rebooted:
-            # Tell clients the device went away.  Careful not to call the overridden
-            # subclass version that closes the serial port
-            MeshInterface._disconnected(self)
-
-            self._startConfig()  # redownload the node db etc...
-        else:
-            logging.debug("Unexpected FromRadio payload")
-
-    def _fixupPosition(self, position):
-        """Convert integer lat/lon into floats
-
-        Arguments:
-            position {Position dictionary} -- object ot fix up
-        """
-        if "latitudeI" in position:
-            position["latitude"] = position["latitudeI"] * 1e-7
-        if "longitudeI" in position:
-            position["longitude"] = position["longitudeI"] * 1e-7
-
-    def _nodeNumToId(self, num):
-        """Map a node node number to a node ID
-
-        Arguments:
-            num {int} -- Node number
-
-        Returns:
-            string -- Node ID
-        """
-        if num == BROADCAST_NUM:
-            return BROADCAST_ADDR
-
-        try:
-            return self.nodesByNum[num]["user"]["id"]
-        except:
-            logging.debug(f"Node {num} not found for fromId")
-            return None
-
-    def _getOrCreateByNum(self, nodeNum):
-        """Given a nodenum find the NodeInfo in the DB (or create if necessary)"""
-        if nodeNum == BROADCAST_NUM:
-            raise Exception("Can not create/find nodenum by the broadcast num")
-
-        if nodeNum in self.nodesByNum:
-            return self.nodesByNum[nodeNum]
-        else:
-            n = {"num": nodeNum}  # Create a minimial node db entry
-            self.nodesByNum[nodeNum] = n
-            return n
-
-    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
-        # doesn't need to understand protobufs.  But advanced clients might
-        # want the raw protobuf, so we provide it in "raw"
-        asDict["raw"] = meshPacket
-
-        # from might be missing if the nodenum was zero.
-        if not hack and "from" not in asDict:
-            asDict["from"] = 0
-            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
-
-        # /add fromId and toId fields based on the node ID
-        try:
-            asDict["fromId"] = self._nodeNumToId(asDict["from"])
-        except Exception as ex:
-            logging.warning(f"Not populating fromId {ex}")
-        try:
-            asDict["toId"] = self._nodeNumToId(asDict["to"])
-        except Exception as ex:
-            logging.warning(f"Not populating toId {ex}")
-
-        # We could provide our objects as DotMaps - which work with . notation or as dictionaries
-        # asObj = DotMap(asDict)
-        topic = "meshtastic.receive"  # Generic unknown packet type
-
-        decoded = asDict["decoded"]
-        # The default MessageToDict converts byte arrays into base64 strings.
-        # We don't want that - it messes up data payload.  So slam in the correct
-        # byte array.
-        decoded["payload"] = meshPacket.decoded.payload
-
-        # 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 "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"]
-
-        topic = f"meshtastic.receive.data.{portnum}"
-
-        # decode position protobufs and update nodedb, provide decoded version
-        # as "position" in the published msg move the following into a 'decoders'
-        # API that clients could register?
-        portNumInt = meshPacket.decoded.portnum  # we want portnum as an int
-        handler = protocols.get(portNumInt)
-        # The decoded protobuf as a dictionary (if we understand this message)
-        p = None
-        if handler is not None:
-            topic = f"meshtastic.receive.{handler.name}"
-
-            # Convert to protobuf if possible
-            if handler.protobufFactory is not None:
-                pb = handler.protobufFactory()
-                pb.ParseFromString(meshPacket.decoded.payload)
-                p = google.protobuf.json_format.MessageToDict(pb)
-                asDict["decoded"][handler.name] = p
-                # Also provide the protobuf raw
-                asDict["decoded"][handler.name]["raw"] = pb
-
-            # Call specialized onReceive if necessary
-            if handler.onReceive is not None:
-                handler.onReceive(self, asDict)
-
-        # Is this message in response to a request, if so, look for a handler
-        requestId = decoded.get("requestId")
-        if requestId is not None:
-            # We ignore ACK packets, but send NAKs and data responses to the handlers
-            routing = decoded.get("routing")
-            isAck = routing is not None and ("errorReason" not in routing)
-            if not isAck:
-                # we keep the responseHandler in dict until we get a non ack
-                handler = self.responseHandlers.pop(requestId, None)
-                if handler is not None:
-                    handler.callback(asDict)
-
-        logging.debug(f"Publishing {topic}: packet={stripnl(asDict)} ")
-        publishingThread.queueWork(lambda: pub.sendMessage(
-            topic, packet=asDict, interface=self))
-
-

Subclasses

- -

Methods

-
-
-def close(self) -
-
-

Shutdown this interface

-
- -Expand source code - -
def close(self):
-    """Shutdown this interface"""
-    if self.heartbeatTimer:
-        self.heartbeatTimer.cancel()
-
-    self._sendDisconnect()
-
-
-
-def getLongName(self) -
-
-

Get long name

-
- -Expand source code - -
def getLongName(self):
-    """Get long name"""
-    user = self.getMyUser()
-    if user is not None:
-        return user.get('longName', None)
-    return None
-
-
-
-def getMyNodeInfo(self) -
-
-

Get info about my node.

-
- -Expand source code - -
def getMyNodeInfo(self):
-    """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) -
-
-

Get user

-
- -Expand source code - -
def getMyUser(self):
-    """Get user"""
-    nodeInfo = self.getMyNodeInfo()
-    if nodeInfo is not None:
-        return nodeInfo.get('user')
-    return None
-
-
-
-def getNode(self, nodeId) -
-
-

Return a node object which contains device settings and channel info

-
- -Expand source code - -
def getNode(self, nodeId):
-    """Return a node object which contains device settings and channel info"""
-    if nodeId == LOCAL_ADDR:
-        return self.localNode
-    else:
-        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")
-        return n
-
-
-
-def getShortName(self) -
-
-

Get short name

-
- -Expand source code - -
def getShortName(self):
-    """Get short name"""
-    user = self.getMyUser()
-    if user is not None:
-        return user.get('shortName', None)
-    return None
-
-
-
-def sendData(self, data, destinationId='^all', portNum=256, wantAck=False, wantResponse=False, hopLimit=None, onResponse=None, channelIndex=0) -
-
-

Send a data packet to some other node

-

Keyword Arguments: -data – the data to send, either as an array of bytes or -as a protobuf (which will be automatically -serialized to bytes) -destinationId {nodeId or nodeNum} – where to send this -message (default: {BROADCAST_ADDR}) -portNum – the application portnum (similar to IP port numbers) -of the destination, see portnums.proto for a list -wantAck – True if you want the message sent in a reliable -manner (with retries and ack/nak provided for delivery) -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) -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.

-
- -Expand source code - -
def sendData(self, data, destinationId=BROADCAST_ADDR,
-             portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
-             wantResponse=False,
-             hopLimit=None,
-             onResponse=None,
-             channelIndex=0):
-    """Send a data packet to some other node
-
-    Keyword Arguments:
-        data -- the data to send, either as an array of bytes or
-                as a protobuf (which will be automatically
-                serialized to bytes)
-        destinationId {nodeId or nodeNum} -- where to send this
-                message (default: {BROADCAST_ADDR})
-        portNum -- the application portnum (similar to IP port numbers)
-                of the destination, see portnums.proto for a list
-        wantAck -- True if you want the message sent in a reliable
-                manner (with retries and ack/nak provided for delivery)
-        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)
-        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:
-        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")
-
-    meshPacket = mesh_pb2.MeshPacket()
-    meshPacket.channel = channelIndex
-    meshPacket.decoded.payload = data
-    meshPacket.decoded.portnum = portNum
-    meshPacket.decoded.want_response = wantResponse
-
-    p = self._sendPacket(meshPacket, destinationId,
-                         wantAck=wantAck, hopLimit=hopLimit)
-    if onResponse is not None:
-        self._addResponseHandler(p.id, onResponse)
-    return p
-
-
-
-def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0, destinationId='^all', wantAck=False, wantResponse=False) -
-
-

Send a position packet to some other node (normally a broadcast)

-

Also, the device software will notice this packet and use it to automatically -set its notion of the local position.

-

If timeSec is not specified (recommended), we will use the local machine time.

-

Returns the sent packet. The id field will be populated in this packet and -can be used to track future message acks/naks.

-
- -Expand source code - -
def sendPosition(self, latitude=0.0, longitude=0.0, altitude=0, timeSec=0,
-                 destinationId=BROADCAST_ADDR, wantAck=False, wantResponse=False):
-    """
-    Send a position packet to some other node (normally a broadcast)
-
-    Also, the device software will notice this packet and use it to automatically
-    set its notion of the local position.
-
-    If timeSec is not specified (recommended), we will use the local machine time.
-
-    Returns the sent packet. The id field will be populated in this packet and
-    can be used to track future message acks/naks.
-    """
-    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,
-                         wantAck=wantAck,
-                         wantResponse=wantResponse)
-
-
-
-def sendText(self, text: ~AnyStr, destinationId='^all', wantAck=False, wantResponse=False, hopLimit=None, onResponse=None, channelIndex=0) -
-
-

Send a utf8 string to some other node, if the node has a display it -will also be shown on the device.

-

Arguments

-

text {string} – The text to send

-

Keyword Arguments: -destinationId {nodeId or nodeNum} – where to send this -message (default: {BROADCAST_ADDR}) -portNum – the application portnum (similar to IP port numbers) -of the destination, see portnums.proto for a list -wantAck – True if you want the message sent in a reliable manner -(with retries and ack/nak provided for delivery) -wantResponse – True if you want the service on the other side to -send an application layer response

-

Returns the sent packet. The id field will be populated in this packet -and can be used to track future message acks/naks.

-
- -Expand source code - -
def sendText(self, text: AnyStr,
-             destinationId=BROADCAST_ADDR,
-             wantAck=False,
-             wantResponse=False,
-             hopLimit=None,
-             onResponse=None,
-             channelIndex=0):
-    """Send a utf8 string to some other node, if the node has a display it
-       will also be shown on the device.
-
-    Arguments:
-        text {string} -- The text to send
-
-    Keyword Arguments:
-        destinationId {nodeId or nodeNum} -- where to send this
-                                             message (default: {BROADCAST_ADDR})
-        portNum -- the application portnum (similar to IP port numbers)
-                   of the destination, see portnums.proto for a list
-        wantAck -- True if you want the message sent in a reliable manner
-                   (with retries and ack/nak provided for delivery)
-        wantResponse -- True if you want the service on the other side to
-                        send an application layer response
-
-    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,
-                         wantResponse=wantResponse,
-                         hopLimit=hopLimit,
-                         onResponse=onResponse,
-                         channelIndex=channelIndex)
-
-
-
-def showInfo(self, file=sys.stdout) -
-
-

Show human readable summary about this object

-
- -Expand source code - -
def showInfo(self, file=sys.stdout):
-    """Show human readable summary about this object"""
-    owner = f"Owner: {self.getLongName()} ({self.getShortName()})"
-    myinfo = ''
-    if self.myInfo:
-        myinfo = f"\nMy info: {stripnl(MessageToJson(self.myInfo))}"
-    mesh = "\nNodes in mesh:"
-    nodes = ""
-    if self.nodes:
-        for n in self.nodes.values():
-            nodes = nodes + f"  {stripnl(n)}"
-    infos = owner + myinfo + mesh + nodes
-    print(infos)
-    return infos
-
-
-
-def showNodes(self, includeSelf=True, file=sys.stdout) -
-
-

Show table summary of nodes in mesh

-
- -Expand source code - -
def showNodes(self, includeSelf=True, file=sys.stdout):
-    """Show table summary of nodes in mesh"""
-    def formatFloat(value, precision=2, unit=''):
-        """Format a float value with precsion."""
-        return f'{value:.{precision}f}{unit}' if value else None
-
-    def getLH(ts):
-        """Format last heard"""
-        return datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') if ts else None
-
-    def getTimeAgo(ts):
-        """Format how long ago have we heard from this node (aka timeago)."""
-        return timeago.format(datetime.fromtimestamp(ts), datetime.now()) if ts else None
-
-    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
-
-            row = {"N": 0}
-
-            user = node.get('user')
-            if user:
-                row.update({
-                    "User": user['longName'],
-                    "AKA":  user['shortName'],
-                    "ID":   user['id'],
-                })
-
-            pos = node.get('position')
-            if pos:
-                row.update({
-                    "Latitude":  formatFloat(pos.get("latitude"),     4, "°"),
-                    "Longitude": formatFloat(pos.get("longitude"),    4, "°"),
-                    "Altitude":  formatFloat(pos.get("altitude"),     0, " m"),
-                    "Battery":   formatFloat(pos.get("batteryLevel"), 2, "%"),
-                })
-
-            row.update({
-                "SNR":       formatFloat(node.get("snr"), 2, " dB"),
-                "LastHeard": getLH(node.get("lastHeard")),
-                "Since":     getTimeAgo(node.get("lastHeard")),
-            })
-
-            rows.append(row)
-
-    rows.sort(key=lambda r: r.get('LastHeard') or '0000', reverse=True)
-    for i, row in enumerate(rows):
-        row['N'] = i+1
-
-    table = tabulate(rows, headers='keys', missingval='N/A', tablefmt='fancy_grid')
-    print(table)
-    return table
-
-
-
-def waitForConfig(self) -
-
-

Block until radio config is received. Returns True if config has been received.

-
- -Expand source code - -
def waitForConfig(self):
-    """Block until radio config is received. Returns True if config has been received."""
-    success = self._timeout.waitForSet(self, attrs=('myInfo', 'nodes')) and self.localNode.waitForConfig()
-    if not success:
-        raise Exception("Timed out waiting for interface config")
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/mesh_pb2.html b/docs/meshtastic/mesh_pb2.html deleted file mode 100644 index de74a85..0000000 --- a/docs/meshtastic/mesh_pb2.html +++ /dev/null @@ -1,9935 +0,0 @@ - - - - - - -meshtastic.mesh_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.mesh_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: mesh.proto
-
-from google.protobuf.internal import enum_type_wrapper
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-from . import portnums_pb2 as portnums__pb2
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='mesh.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\nMeshProtosH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\nmesh.proto\x1a\x0eportnums.proto\"\x94\x06\n\x08Position\x12\x12\n\nlatitude_i\x18\x01 \x01(\x0f\x12\x13\n\x0blongitude_i\x18\x02 \x01(\x0f\x12\x10\n\x08\x61ltitude\x18\x03 \x01(\x05\x12\x15\n\rbattery_level\x18\x04 \x01(\x05\x12\x0c\n\x04time\x18\t \x01(\x07\x12,\n\x0flocation_source\x18\n \x01(\x0e\x32\x13.Position.LocSource\x12,\n\x0f\x61ltitude_source\x18\x0b \x01(\x0e\x32\x13.Position.AltSource\x12\x15\n\rpos_timestamp\x18\x0c \x01(\x07\x12\x17\n\x0fpos_time_millis\x18\r \x01(\x05\x12\x14\n\x0c\x61ltitude_hae\x18\x0e \x01(\x11\x12\x15\n\ralt_geoid_sep\x18\x0f \x01(\x11\x12\x0c\n\x04PDOP\x18\x10 \x01(\r\x12\x0c\n\x04HDOP\x18\x11 \x01(\r\x12\x0c\n\x04VDOP\x18\x12 \x01(\r\x12\x14\n\x0cgps_accuracy\x18\x13 \x01(\r\x12\x14\n\x0cground_speed\x18\x14 \x01(\r\x12\x14\n\x0cground_track\x18\x15 \x01(\r\x12\x13\n\x0b\x66ix_quality\x18\x16 \x01(\r\x12\x10\n\x08\x66ix_type\x18\x17 \x01(\r\x12\x14\n\x0csats_in_view\x18\x18 \x01(\r\x12\x11\n\tsensor_id\x18\x19 \x01(\r\x12\x17\n\x0fpos_next_update\x18( \x01(\r\x12\x16\n\x0epos_seq_number\x18) \x01(\r\"n\n\tLocSource\x12\x16\n\x12LOCSRC_UNSPECIFIED\x10\x00\x12\x17\n\x13LOCSRC_MANUAL_ENTRY\x10\x01\x12\x17\n\x13LOCSRC_GPS_INTERNAL\x10\x02\x12\x17\n\x13LOCSRC_GPS_EXTERNAL\x10\x03\"\x85\x01\n\tAltSource\x12\x16\n\x12\x41LTSRC_UNSPECIFIED\x10\x00\x12\x17\n\x13\x41LTSRC_MANUAL_ENTRY\x10\x01\x12\x17\n\x13\x41LTSRC_GPS_INTERNAL\x10\x02\x12\x17\n\x13\x41LTSRC_GPS_EXTERNAL\x10\x03\x12\x15\n\x11\x41LTSRC_BAROMETRIC\x10\x04J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\t\"\xd7\x01\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tlong_name\x18\x02 \x01(\t\x12\x12\n\nshort_name\x18\x03 \x01(\t\x12\x0f\n\x07macaddr\x18\x04 \x01(\x0c\x12 \n\x08hw_model\x18\x06 \x01(\x0e\x32\x0e.HardwareModel\x12\x13\n\x0bis_licensed\x18\x07 \x01(\x08\x12\x13\n\x04team\x18\x08 \x01(\x0e\x32\x05.Team\x12\x14\n\x0ctx_power_dbm\x18\n \x01(\r\x12\x14\n\x0c\x61nt_gain_dbi\x18\x0b \x01(\r\x12\x13\n\x0b\x61nt_azimuth\x18\x0c \x01(\r\"\x1f\n\x0eRouteDiscovery\x12\r\n\x05route\x18\x02 \x03(\x07\"\xc5\x02\n\x07Routing\x12(\n\rroute_request\x18\x01 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0broute_reply\x18\x02 \x01(\x0b\x32\x0f.RouteDiscoveryH\x00\x12&\n\x0c\x65rror_reason\x18\x03 \x01(\x0e\x32\x0e.Routing.ErrorH\x00\"\xb4\x01\n\x05\x45rror\x12\x08\n\x04NONE\x10\x00\x12\x0c\n\x08NO_ROUTE\x10\x01\x12\x0b\n\x07GOT_NAK\x10\x02\x12\x0b\n\x07TIMEOUT\x10\x03\x12\x10\n\x0cNO_INTERFACE\x10\x04\x12\x12\n\x0eMAX_RETRANSMIT\x10\x05\x12\x0e\n\nNO_CHANNEL\x10\x06\x12\r\n\tTOO_LARGE\x10\x07\x12\x0f\n\x0bNO_RESPONSE\x10\x08\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10 \x12\x12\n\x0eNOT_AUTHORIZED\x10!B\t\n\x07variant\"{\n\x04\x44\x61ta\x12\x19\n\x07portnum\x18\x01 \x01(\x0e\x32\x08.PortNum\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\x12\x15\n\rwant_response\x18\x03 \x01(\x08\x12\x0c\n\x04\x64\x65st\x18\x04 \x01(\x07\x12\x0e\n\x06source\x18\x05 \x01(\x07\x12\x12\n\nrequest_id\x18\x06 \x01(\x07\"\xf0\x03\n\nMeshPacket\x12\x0c\n\x04\x66rom\x18\x01 \x01(\x07\x12\n\n\x02to\x18\x02 \x01(\x07\x12\x0f\n\x07\x63hannel\x18\x03 \x01(\r\x12\x18\n\x07\x64\x65\x63oded\x18\x04 \x01(\x0b\x32\x05.DataH\x00\x12\x13\n\tencrypted\x18\x05 \x01(\x0cH\x00\x12\n\n\x02id\x18\x06 \x01(\x07\x12\x0f\n\x07rx_time\x18\x07 \x01(\x07\x12\x0e\n\x06rx_snr\x18\x08 \x01(\x02\x12\x11\n\thop_limit\x18\n \x01(\r\x12\x10\n\x08want_ack\x18\x0b \x01(\x08\x12&\n\x08priority\x18\x0c \x01(\x0e\x32\x14.MeshPacket.Priority\x12\x0f\n\x07rx_rssi\x18\r \x01(\x05\x12$\n\x07\x64\x65layed\x18\x0f \x01(\x0e\x32\x13.MeshPacket.Delayed\x12\x10\n\x08reply_id\x18\x10 \x01(\x07\x12\x12\n\nis_tapback\x18\x11 \x01(\x08\"[\n\x08Priority\x12\t\n\x05UNSET\x10\x00\x12\x07\n\x03MIN\x10\x01\x12\x0e\n\nBACKGROUND\x10\n\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10@\x12\x0c\n\x08RELIABLE\x10\x46\x12\x07\n\x03\x41\x43K\x10x\x12\x07\n\x03MAX\x10\x7f\"B\n\x07\x44\x65layed\x12\x0c\n\x08NO_DELAY\x10\x00\x12\x15\n\x11\x44\x45LAYED_BROADCAST\x10\x01\x12\x12\n\x0e\x44\x45LAYED_DIRECT\x10\x02\x42\x10\n\x0epayloadVariant\"j\n\x08NodeInfo\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x13\n\x04user\x18\x02 \x01(\x0b\x32\x05.User\x12\x1b\n\x08position\x18\x03 \x01(\x0b\x32\t.Position\x12\x0b\n\x03snr\x18\x07 \x01(\x02\x12\x12\n\nlast_heard\x18\x04 \x01(\x07\"\xb9\x03\n\nMyNodeInfo\x12\x13\n\x0bmy_node_num\x18\x01 \x01(\r\x12\x0f\n\x07has_gps\x18\x02 \x01(\x08\x12\x11\n\tnum_bands\x18\x03 \x01(\r\x12\x14\n\x0cmax_channels\x18\x0f \x01(\r\x12\x12\n\x06region\x18\x04 \x01(\tB\x02\x18\x01\x12\x1f\n\x13hw_model_deprecated\x18\x05 \x01(\tB\x02\x18\x01\x12\x18\n\x10\x66irmware_version\x18\x06 \x01(\t\x12&\n\nerror_code\x18\x07 \x01(\x0e\x32\x12.CriticalErrorCode\x12\x15\n\rerror_address\x18\x08 \x01(\r\x12\x13\n\x0b\x65rror_count\x18\t \x01(\r\x12\x14\n\x0creboot_count\x18\n \x01(\r\x12\x0f\n\x07\x62itrate\x18\x0b \x01(\x02\x12\x1c\n\x14message_timeout_msec\x18\r \x01(\r\x12\x17\n\x0fmin_app_version\x18\x0e \x01(\r\x12\x15\n\rair_period_tx\x18\x10 \x03(\r\x12\x15\n\rair_period_rx\x18\x11 \x03(\r\x12\x10\n\x08has_wifi\x18\x12 \x01(\x08\x12\x1b\n\x13\x63hannel_utilization\x18\x13 \x01(\x02\"\xb5\x01\n\tLogRecord\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04time\x18\x02 \x01(\x07\x12\x0e\n\x06source\x18\x03 \x01(\t\x12\x1f\n\x05level\x18\x04 \x01(\x0e\x32\x10.LogRecord.Level\"X\n\x05Level\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x43RITICAL\x10\x32\x12\t\n\x05\x45RROR\x10(\x12\x0b\n\x07WARNING\x10\x1e\x12\x08\n\x04INFO\x10\x14\x12\t\n\x05\x44\x45\x42UG\x10\n\x12\t\n\x05TRACE\x10\x05\"\xe9\x01\n\tFromRadio\x12\x0b\n\x03num\x18\x01 \x01(\r\x12\x1d\n\x06packet\x18\x0b \x01(\x0b\x32\x0b.MeshPacketH\x00\x12\x1e\n\x07my_info\x18\x03 \x01(\x0b\x32\x0b.MyNodeInfoH\x00\x12\x1e\n\tnode_info\x18\x04 \x01(\x0b\x32\t.NodeInfoH\x00\x12 \n\nlog_record\x18\x07 \x01(\x0b\x32\n.LogRecordH\x00\x12\x1c\n\x12\x63onfig_complete_id\x18\x08 \x01(\rH\x00\x12\x12\n\x08rebooted\x18\t \x01(\x08H\x00\x42\x10\n\x0epayloadVariantJ\x04\x08\x02\x10\x03J\x04\x08\x06\x10\x07\"\xe1\x01\n\x07ToRadio\x12\x1d\n\x06packet\x18\x02 \x01(\x0b\x32\x0b.MeshPacketH\x00\x12&\n\tpeer_info\x18\x03 \x01(\x0b\x32\x11.ToRadio.PeerInfoH\x00\x12\x18\n\x0ewant_config_id\x18\x64 \x01(\rH\x00\x12\x14\n\ndisconnect\x18h \x01(\x08H\x00\x1a\x35\n\x08PeerInfo\x12\x13\n\x0b\x61pp_version\x18\x01 \x01(\r\x12\x14\n\x0cmqtt_gateway\x18\x02 \x01(\x08\x42\x10\n\x0epayloadVariantJ\x04\x08\x01\x10\x02J\x04\x08\x65\x10\x66J\x04\x08\x66\x10gJ\x04\x08g\x10h*\xac\x02\n\rHardwareModel\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08TLORA_V2\x10\x01\x12\x0c\n\x08TLORA_V1\x10\x02\x12\x12\n\x0eTLORA_V2_1_1p6\x10\x03\x12\t\n\x05TBEAM\x10\x04\x12\x0f\n\x0bHELTEC_V2_0\x10\x05\x12\x0c\n\x08TBEAM0p7\x10\x06\x12\n\n\x06T_ECHO\x10\x07\x12\x10\n\x0cTLORA_V1_1p3\x10\x08\x12\x0b\n\x07RAK4631\x10\t\x12\x0f\n\x0bHELTEC_V2_1\x10\n\x12\x11\n\rLORA_RELAY_V1\x10 \x12\x0e\n\nNRF52840DK\x10!\x12\x07\n\x03PPR\x10\"\x12\x0f\n\x0bGENIEBLOCKS\x10#\x12\x11\n\rNRF52_UNKNOWN\x10$\x12\r\n\tPORTDUINO\x10%\x12\x0f\n\x0b\x41NDROID_SIM\x10&\x12\n\n\x06\x44IY_V1\x10\'*\xb5\x01\n\x04Team\x12\t\n\x05\x43LEAR\x10\x00\x12\x08\n\x04\x43YAN\x10\x01\x12\t\n\x05WHITE\x10\x02\x12\n\n\x06YELLOW\x10\x03\x12\n\n\x06ORANGE\x10\x04\x12\x0b\n\x07MAGENTA\x10\x05\x12\x07\n\x03RED\x10\x06\x12\n\n\x06MAROON\x10\x07\x12\n\n\x06PURPLE\x10\x08\x12\r\n\tDARK_BLUE\x10\t\x12\x08\n\x04\x42LUE\x10\n\x12\x08\n\x04TEAL\x10\x0b\x12\t\n\x05GREEN\x10\x0c\x12\x0e\n\nDARK_GREEN\x10\r\x12\t\n\x05\x42ROWN\x10\x0e*.\n\tConstants\x12\n\n\x06Unused\x10\x00\x12\x15\n\x10\x44\x41TA_PAYLOAD_LEN\x10\xed\x01*\xe1\x01\n\x11\x43riticalErrorCode\x12\x08\n\x04None\x10\x00\x12\x0e\n\nTxWatchdog\x10\x01\x12\x12\n\x0eSleepEnterWait\x10\x02\x12\x0b\n\x07NoRadio\x10\x03\x12\x0f\n\x0bUnspecified\x10\x04\x12\x13\n\x0fUBloxInitFailed\x10\x05\x12\x0c\n\x08NoAXP192\x10\x06\x12\x17\n\x13InvalidRadioSetting\x10\x07\x12\x12\n\x0eTransmitFailed\x10\x08\x12\x0c\n\x08\x42rownout\x10\t\x12\x11\n\rSX1262Failure\x10\n\x12\x0f\n\x0bRadioSpiBug\x10\x0b\x42\x46\n\x13\x63om.geeksville.meshB\nMeshProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-  ,
-  dependencies=[portnums__pb2.DESCRIPTOR,])
-
-_HARDWAREMODEL = _descriptor.EnumDescriptor(
-  name='HardwareModel',
-  full_name='HardwareModel',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='UNSET', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TLORA_V2', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TLORA_V1', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TLORA_V2_1_1p6', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TBEAM', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='HELTEC_V2_0', index=5, number=5,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TBEAM0p7', index=6, number=6,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='T_ECHO', index=7, number=7,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TLORA_V1_1p3', index=8, number=8,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='RAK4631', index=9, number=9,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='HELTEC_V2_1', index=10, number=10,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='LORA_RELAY_V1', index=11, number=32,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NRF52840DK', index=12, number=33,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='PPR', index=13, number=34,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GENIEBLOCKS', index=14, number=35,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NRF52_UNKNOWN', index=15, number=36,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='PORTDUINO', index=16, number=37,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ANDROID_SIM', index=17, number=38,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='DIY_V1', index=18, number=39,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=3225,
-  serialized_end=3525,
-)
-_sym_db.RegisterEnumDescriptor(_HARDWAREMODEL)
-
-HardwareModel = enum_type_wrapper.EnumTypeWrapper(_HARDWAREMODEL)
-_TEAM = _descriptor.EnumDescriptor(
-  name='Team',
-  full_name='Team',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='CLEAR', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='CYAN', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='WHITE', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='YELLOW', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ORANGE', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MAGENTA', index=5, number=5,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='RED', index=6, number=6,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MAROON', index=7, number=7,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='PURPLE', index=8, number=8,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='DARK_BLUE', index=9, number=9,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='BLUE', index=10, number=10,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TEAL', index=11, number=11,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GREEN', index=12, number=12,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='DARK_GREEN', index=13, number=13,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='BROWN', index=14, number=14,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=3528,
-  serialized_end=3709,
-)
-_sym_db.RegisterEnumDescriptor(_TEAM)
-
-Team = enum_type_wrapper.EnumTypeWrapper(_TEAM)
-_CONSTANTS = _descriptor.EnumDescriptor(
-  name='Constants',
-  full_name='Constants',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='Unused', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='DATA_PAYLOAD_LEN', index=1, number=237,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=3711,
-  serialized_end=3757,
-)
-_sym_db.RegisterEnumDescriptor(_CONSTANTS)
-
-Constants = enum_type_wrapper.EnumTypeWrapper(_CONSTANTS)
-_CRITICALERRORCODE = _descriptor.EnumDescriptor(
-  name='CriticalErrorCode',
-  full_name='CriticalErrorCode',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='None', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TxWatchdog', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='SleepEnterWait', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NoRadio', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='Unspecified', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='UBloxInitFailed', index=5, number=5,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NoAXP192', index=6, number=6,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='InvalidRadioSetting', index=7, number=7,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TransmitFailed', index=8, number=8,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='Brownout', index=9, number=9,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='SX1262Failure', index=10, number=10,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='RadioSpiBug', index=11, number=11,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=3760,
-  serialized_end=3985,
-)
-_sym_db.RegisterEnumDescriptor(_CRITICALERRORCODE)
-
-CriticalErrorCode = enum_type_wrapper.EnumTypeWrapper(_CRITICALERRORCODE)
-UNSET = 0
-TLORA_V2 = 1
-TLORA_V1 = 2
-TLORA_V2_1_1p6 = 3
-TBEAM = 4
-HELTEC_V2_0 = 5
-TBEAM0p7 = 6
-T_ECHO = 7
-TLORA_V1_1p3 = 8
-RAK4631 = 9
-HELTEC_V2_1 = 10
-LORA_RELAY_V1 = 32
-NRF52840DK = 33
-PPR = 34
-GENIEBLOCKS = 35
-NRF52_UNKNOWN = 36
-PORTDUINO = 37
-ANDROID_SIM = 38
-DIY_V1 = 39
-CLEAR = 0
-CYAN = 1
-WHITE = 2
-YELLOW = 3
-ORANGE = 4
-MAGENTA = 5
-RED = 6
-MAROON = 7
-PURPLE = 8
-DARK_BLUE = 9
-BLUE = 10
-TEAL = 11
-GREEN = 12
-DARK_GREEN = 13
-BROWN = 14
-Unused = 0
-DATA_PAYLOAD_LEN = 237
-globals()['None'] = 0
-TxWatchdog = 1
-SleepEnterWait = 2
-NoRadio = 3
-Unspecified = 4
-UBloxInitFailed = 5
-NoAXP192 = 6
-InvalidRadioSetting = 7
-TransmitFailed = 8
-Brownout = 9
-SX1262Failure = 10
-RadioSpiBug = 11
-
-
-_POSITION_LOCSOURCE = _descriptor.EnumDescriptor(
-  name='LocSource',
-  full_name='Position.LocSource',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='LOCSRC_UNSPECIFIED', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='LOCSRC_MANUAL_ENTRY', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='LOCSRC_GPS_INTERNAL', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='LOCSRC_GPS_EXTERNAL', index=3, number=3,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=561,
-  serialized_end=671,
-)
-_sym_db.RegisterEnumDescriptor(_POSITION_LOCSOURCE)
-
-_POSITION_ALTSOURCE = _descriptor.EnumDescriptor(
-  name='AltSource',
-  full_name='Position.AltSource',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='ALTSRC_UNSPECIFIED', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ALTSRC_MANUAL_ENTRY', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ALTSRC_GPS_INTERNAL', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ALTSRC_GPS_EXTERNAL', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ALTSRC_BAROMETRIC', index=4, number=4,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=674,
-  serialized_end=807,
-)
-_sym_db.RegisterEnumDescriptor(_POSITION_ALTSOURCE)
-
-_ROUTING_ERROR = _descriptor.EnumDescriptor(
-  name='Error',
-  full_name='Routing.Error',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='NONE', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NO_ROUTE', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GOT_NAK', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TIMEOUT', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NO_INTERFACE', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MAX_RETRANSMIT', index=5, number=5,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NO_CHANNEL', index=6, number=6,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TOO_LARGE', index=7, number=7,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NO_RESPONSE', index=8, number=8,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='BAD_REQUEST', index=9, number=32,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NOT_AUTHORIZED', index=10, number=33,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=1207,
-  serialized_end=1387,
-)
-_sym_db.RegisterEnumDescriptor(_ROUTING_ERROR)
-
-_MESHPACKET_PRIORITY = _descriptor.EnumDescriptor(
-  name='Priority',
-  full_name='MeshPacket.Priority',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='UNSET', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MIN', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='BACKGROUND', index=2, number=10,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='DEFAULT', index=3, number=64,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='RELIABLE', index=4, number=70,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ACK', index=5, number=120,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MAX', index=6, number=127,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=1845,
-  serialized_end=1936,
-)
-_sym_db.RegisterEnumDescriptor(_MESHPACKET_PRIORITY)
-
-_MESHPACKET_DELAYED = _descriptor.EnumDescriptor(
-  name='Delayed',
-  full_name='MeshPacket.Delayed',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='NO_DELAY', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='DELAYED_BROADCAST', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='DELAYED_DIRECT', index=2, number=2,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=1938,
-  serialized_end=2004,
-)
-_sym_db.RegisterEnumDescriptor(_MESHPACKET_DELAYED)
-
-_LOGRECORD_LEVEL = _descriptor.EnumDescriptor(
-  name='Level',
-  full_name='LogRecord.Level',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='UNSET', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='CRITICAL', index=1, number=50,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ERROR', index=2, number=40,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='WARNING', index=3, number=30,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='INFO', index=4, number=20,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='DEBUG', index=5, number=10,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TRACE', index=6, number=5,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=2670,
-  serialized_end=2758,
-)
-_sym_db.RegisterEnumDescriptor(_LOGRECORD_LEVEL)
-
-
-_POSITION = _descriptor.Descriptor(
-  name='Position',
-  full_name='Position',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='latitude_i', full_name='Position.latitude_i', index=0,
-      number=1, type=15, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='longitude_i', full_name='Position.longitude_i', index=1,
-      number=2, type=15, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='altitude', full_name='Position.altitude', index=2,
-      number=3, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='battery_level', full_name='Position.battery_level', index=3,
-      number=4, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='time', full_name='Position.time', index=4,
-      number=9, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='location_source', full_name='Position.location_source', index=5,
-      number=10, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='altitude_source', full_name='Position.altitude_source', index=6,
-      number=11, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='pos_timestamp', full_name='Position.pos_timestamp', index=7,
-      number=12, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='pos_time_millis', full_name='Position.pos_time_millis', index=8,
-      number=13, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='altitude_hae', full_name='Position.altitude_hae', index=9,
-      number=14, type=17, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='alt_geoid_sep', full_name='Position.alt_geoid_sep', index=10,
-      number=15, type=17, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='PDOP', full_name='Position.PDOP', index=11,
-      number=16, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='HDOP', full_name='Position.HDOP', index=12,
-      number=17, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='VDOP', full_name='Position.VDOP', index=13,
-      number=18, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gps_accuracy', full_name='Position.gps_accuracy', index=14,
-      number=19, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ground_speed', full_name='Position.ground_speed', index=15,
-      number=20, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ground_track', full_name='Position.ground_track', index=16,
-      number=21, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='fix_quality', full_name='Position.fix_quality', index=17,
-      number=22, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='fix_type', full_name='Position.fix_type', index=18,
-      number=23, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='sats_in_view', full_name='Position.sats_in_view', index=19,
-      number=24, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='sensor_id', full_name='Position.sensor_id', index=20,
-      number=25, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='pos_next_update', full_name='Position.pos_next_update', index=21,
-      number=40, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='pos_seq_number', full_name='Position.pos_seq_number', index=22,
-      number=41, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-    _POSITION_LOCSOURCE,
-    _POSITION_ALTSOURCE,
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=31,
-  serialized_end=819,
-)
-
-
-_USER = _descriptor.Descriptor(
-  name='User',
-  full_name='User',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='id', full_name='User.id', index=0,
-      number=1, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='long_name', full_name='User.long_name', index=1,
-      number=2, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='short_name', full_name='User.short_name', index=2,
-      number=3, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='macaddr', full_name='User.macaddr', index=3,
-      number=4, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"",
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='hw_model', full_name='User.hw_model', index=4,
-      number=6, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='is_licensed', full_name='User.is_licensed', index=5,
-      number=7, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='team', full_name='User.team', index=6,
-      number=8, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='tx_power_dbm', full_name='User.tx_power_dbm', index=7,
-      number=10, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ant_gain_dbi', full_name='User.ant_gain_dbi', index=8,
-      number=11, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ant_azimuth', full_name='User.ant_azimuth', index=9,
-      number=12, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=822,
-  serialized_end=1037,
-)
-
-
-_ROUTEDISCOVERY = _descriptor.Descriptor(
-  name='RouteDiscovery',
-  full_name='RouteDiscovery',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='route', full_name='RouteDiscovery.route', index=0,
-      number=2, type=7, cpp_type=3, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=1039,
-  serialized_end=1070,
-)
-
-
-_ROUTING = _descriptor.Descriptor(
-  name='Routing',
-  full_name='Routing',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='route_request', full_name='Routing.route_request', index=0,
-      number=1, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='route_reply', full_name='Routing.route_reply', index=1,
-      number=2, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='error_reason', full_name='Routing.error_reason', index=2,
-      number=3, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-    _ROUTING_ERROR,
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-    _descriptor.OneofDescriptor(
-      name='variant', full_name='Routing.variant',
-      index=0, containing_type=None, fields=[]),
-  ],
-  serialized_start=1073,
-  serialized_end=1398,
-)
-
-
-_DATA = _descriptor.Descriptor(
-  name='Data',
-  full_name='Data',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='portnum', full_name='Data.portnum', index=0,
-      number=1, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='payload', full_name='Data.payload', index=1,
-      number=2, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"",
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='want_response', full_name='Data.want_response', index=2,
-      number=3, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='dest', full_name='Data.dest', index=3,
-      number=4, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='source', full_name='Data.source', index=4,
-      number=5, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='request_id', full_name='Data.request_id', index=5,
-      number=6, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=1400,
-  serialized_end=1523,
-)
-
-
-_MESHPACKET = _descriptor.Descriptor(
-  name='MeshPacket',
-  full_name='MeshPacket',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='from', full_name='MeshPacket.from', index=0,
-      number=1, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='to', full_name='MeshPacket.to', index=1,
-      number=2, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='channel', full_name='MeshPacket.channel', index=2,
-      number=3, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='decoded', full_name='MeshPacket.decoded', index=3,
-      number=4, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='encrypted', full_name='MeshPacket.encrypted', index=4,
-      number=5, type=12, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"",
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='id', full_name='MeshPacket.id', index=5,
-      number=6, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='rx_time', full_name='MeshPacket.rx_time', index=6,
-      number=7, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='rx_snr', full_name='MeshPacket.rx_snr', index=7,
-      number=8, type=2, cpp_type=6, label=1,
-      has_default_value=False, default_value=float(0),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='hop_limit', full_name='MeshPacket.hop_limit', index=8,
-      number=10, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='want_ack', full_name='MeshPacket.want_ack', index=9,
-      number=11, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='priority', full_name='MeshPacket.priority', index=10,
-      number=12, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='rx_rssi', full_name='MeshPacket.rx_rssi', index=11,
-      number=13, type=5, cpp_type=1, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='delayed', full_name='MeshPacket.delayed', index=12,
-      number=15, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='reply_id', full_name='MeshPacket.reply_id', index=13,
-      number=16, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='is_tapback', full_name='MeshPacket.is_tapback', index=14,
-      number=17, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-    _MESHPACKET_PRIORITY,
-    _MESHPACKET_DELAYED,
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-    _descriptor.OneofDescriptor(
-      name='payloadVariant', full_name='MeshPacket.payloadVariant',
-      index=0, containing_type=None, fields=[]),
-  ],
-  serialized_start=1526,
-  serialized_end=2022,
-)
-
-
-_NODEINFO = _descriptor.Descriptor(
-  name='NodeInfo',
-  full_name='NodeInfo',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='num', full_name='NodeInfo.num', index=0,
-      number=1, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='user', full_name='NodeInfo.user', index=1,
-      number=2, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='position', full_name='NodeInfo.position', index=2,
-      number=3, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='snr', full_name='NodeInfo.snr', index=3,
-      number=7, type=2, cpp_type=6, label=1,
-      has_default_value=False, default_value=float(0),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='last_heard', full_name='NodeInfo.last_heard', index=4,
-      number=4, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=2024,
-  serialized_end=2130,
-)
-
-
-_MYNODEINFO = _descriptor.Descriptor(
-  name='MyNodeInfo',
-  full_name='MyNodeInfo',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='my_node_num', full_name='MyNodeInfo.my_node_num', index=0,
-      number=1, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='has_gps', full_name='MyNodeInfo.has_gps', index=1,
-      number=2, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='num_bands', full_name='MyNodeInfo.num_bands', index=2,
-      number=3, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='max_channels', full_name='MyNodeInfo.max_channels', index=3,
-      number=15, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='region', full_name='MyNodeInfo.region', index=4,
-      number=4, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=b'\030\001', file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='hw_model_deprecated', full_name='MyNodeInfo.hw_model_deprecated', index=5,
-      number=5, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=b'\030\001', file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='firmware_version', full_name='MyNodeInfo.firmware_version', index=6,
-      number=6, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='error_code', full_name='MyNodeInfo.error_code', index=7,
-      number=7, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='error_address', full_name='MyNodeInfo.error_address', index=8,
-      number=8, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='error_count', full_name='MyNodeInfo.error_count', index=9,
-      number=9, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='reboot_count', full_name='MyNodeInfo.reboot_count', index=10,
-      number=10, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='bitrate', full_name='MyNodeInfo.bitrate', index=11,
-      number=11, type=2, cpp_type=6, label=1,
-      has_default_value=False, default_value=float(0),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='message_timeout_msec', full_name='MyNodeInfo.message_timeout_msec', index=12,
-      number=13, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='min_app_version', full_name='MyNodeInfo.min_app_version', index=13,
-      number=14, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='air_period_tx', full_name='MyNodeInfo.air_period_tx', index=14,
-      number=16, type=13, cpp_type=3, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='air_period_rx', full_name='MyNodeInfo.air_period_rx', index=15,
-      number=17, type=13, cpp_type=3, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='has_wifi', full_name='MyNodeInfo.has_wifi', index=16,
-      number=18, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='channel_utilization', full_name='MyNodeInfo.channel_utilization', index=17,
-      number=19, type=2, cpp_type=6, label=1,
-      has_default_value=False, default_value=float(0),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=2133,
-  serialized_end=2574,
-)
-
-
-_LOGRECORD = _descriptor.Descriptor(
-  name='LogRecord',
-  full_name='LogRecord',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='message', full_name='LogRecord.message', index=0,
-      number=1, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='time', full_name='LogRecord.time', index=1,
-      number=2, type=7, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='source', full_name='LogRecord.source', index=2,
-      number=3, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='level', full_name='LogRecord.level', index=3,
-      number=4, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-    _LOGRECORD_LEVEL,
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=2577,
-  serialized_end=2758,
-)
-
-
-_FROMRADIO = _descriptor.Descriptor(
-  name='FromRadio',
-  full_name='FromRadio',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='num', full_name='FromRadio.num', index=0,
-      number=1, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='packet', full_name='FromRadio.packet', index=1,
-      number=11, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='my_info', full_name='FromRadio.my_info', index=2,
-      number=3, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='node_info', full_name='FromRadio.node_info', index=3,
-      number=4, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='log_record', full_name='FromRadio.log_record', index=4,
-      number=7, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='config_complete_id', full_name='FromRadio.config_complete_id', index=5,
-      number=8, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='rebooted', full_name='FromRadio.rebooted', index=6,
-      number=9, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-    _descriptor.OneofDescriptor(
-      name='payloadVariant', full_name='FromRadio.payloadVariant',
-      index=0, containing_type=None, fields=[]),
-  ],
-  serialized_start=2761,
-  serialized_end=2994,
-)
-
-
-_TORADIO_PEERINFO = _descriptor.Descriptor(
-  name='PeerInfo',
-  full_name='ToRadio.PeerInfo',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='app_version', full_name='ToRadio.PeerInfo.app_version', index=0,
-      number=1, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='mqtt_gateway', full_name='ToRadio.PeerInfo.mqtt_gateway', index=1,
-      number=2, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=3127,
-  serialized_end=3180,
-)
-
-_TORADIO = _descriptor.Descriptor(
-  name='ToRadio',
-  full_name='ToRadio',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='packet', full_name='ToRadio.packet', index=0,
-      number=2, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='peer_info', full_name='ToRadio.peer_info', index=1,
-      number=3, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='want_config_id', full_name='ToRadio.want_config_id', index=2,
-      number=100, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='disconnect', full_name='ToRadio.disconnect', index=3,
-      number=104, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[_TORADIO_PEERINFO, ],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-    _descriptor.OneofDescriptor(
-      name='payloadVariant', full_name='ToRadio.payloadVariant',
-      index=0, containing_type=None, fields=[]),
-  ],
-  serialized_start=2997,
-  serialized_end=3222,
-)
-
-_POSITION.fields_by_name['location_source'].enum_type = _POSITION_LOCSOURCE
-_POSITION.fields_by_name['altitude_source'].enum_type = _POSITION_ALTSOURCE
-_POSITION_LOCSOURCE.containing_type = _POSITION
-_POSITION_ALTSOURCE.containing_type = _POSITION
-_USER.fields_by_name['hw_model'].enum_type = _HARDWAREMODEL
-_USER.fields_by_name['team'].enum_type = _TEAM
-_ROUTING.fields_by_name['route_request'].message_type = _ROUTEDISCOVERY
-_ROUTING.fields_by_name['route_reply'].message_type = _ROUTEDISCOVERY
-_ROUTING.fields_by_name['error_reason'].enum_type = _ROUTING_ERROR
-_ROUTING_ERROR.containing_type = _ROUTING
-_ROUTING.oneofs_by_name['variant'].fields.append(
-  _ROUTING.fields_by_name['route_request'])
-_ROUTING.fields_by_name['route_request'].containing_oneof = _ROUTING.oneofs_by_name['variant']
-_ROUTING.oneofs_by_name['variant'].fields.append(
-  _ROUTING.fields_by_name['route_reply'])
-_ROUTING.fields_by_name['route_reply'].containing_oneof = _ROUTING.oneofs_by_name['variant']
-_ROUTING.oneofs_by_name['variant'].fields.append(
-  _ROUTING.fields_by_name['error_reason'])
-_ROUTING.fields_by_name['error_reason'].containing_oneof = _ROUTING.oneofs_by_name['variant']
-_DATA.fields_by_name['portnum'].enum_type = portnums__pb2._PORTNUM
-_MESHPACKET.fields_by_name['decoded'].message_type = _DATA
-_MESHPACKET.fields_by_name['priority'].enum_type = _MESHPACKET_PRIORITY
-_MESHPACKET.fields_by_name['delayed'].enum_type = _MESHPACKET_DELAYED
-_MESHPACKET_PRIORITY.containing_type = _MESHPACKET
-_MESHPACKET_DELAYED.containing_type = _MESHPACKET
-_MESHPACKET.oneofs_by_name['payloadVariant'].fields.append(
-  _MESHPACKET.fields_by_name['decoded'])
-_MESHPACKET.fields_by_name['decoded'].containing_oneof = _MESHPACKET.oneofs_by_name['payloadVariant']
-_MESHPACKET.oneofs_by_name['payloadVariant'].fields.append(
-  _MESHPACKET.fields_by_name['encrypted'])
-_MESHPACKET.fields_by_name['encrypted'].containing_oneof = _MESHPACKET.oneofs_by_name['payloadVariant']
-_NODEINFO.fields_by_name['user'].message_type = _USER
-_NODEINFO.fields_by_name['position'].message_type = _POSITION
-_MYNODEINFO.fields_by_name['error_code'].enum_type = _CRITICALERRORCODE
-_LOGRECORD.fields_by_name['level'].enum_type = _LOGRECORD_LEVEL
-_LOGRECORD_LEVEL.containing_type = _LOGRECORD
-_FROMRADIO.fields_by_name['packet'].message_type = _MESHPACKET
-_FROMRADIO.fields_by_name['my_info'].message_type = _MYNODEINFO
-_FROMRADIO.fields_by_name['node_info'].message_type = _NODEINFO
-_FROMRADIO.fields_by_name['log_record'].message_type = _LOGRECORD
-_FROMRADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _FROMRADIO.fields_by_name['packet'])
-_FROMRADIO.fields_by_name['packet'].containing_oneof = _FROMRADIO.oneofs_by_name['payloadVariant']
-_FROMRADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _FROMRADIO.fields_by_name['my_info'])
-_FROMRADIO.fields_by_name['my_info'].containing_oneof = _FROMRADIO.oneofs_by_name['payloadVariant']
-_FROMRADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _FROMRADIO.fields_by_name['node_info'])
-_FROMRADIO.fields_by_name['node_info'].containing_oneof = _FROMRADIO.oneofs_by_name['payloadVariant']
-_FROMRADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _FROMRADIO.fields_by_name['log_record'])
-_FROMRADIO.fields_by_name['log_record'].containing_oneof = _FROMRADIO.oneofs_by_name['payloadVariant']
-_FROMRADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _FROMRADIO.fields_by_name['config_complete_id'])
-_FROMRADIO.fields_by_name['config_complete_id'].containing_oneof = _FROMRADIO.oneofs_by_name['payloadVariant']
-_FROMRADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _FROMRADIO.fields_by_name['rebooted'])
-_FROMRADIO.fields_by_name['rebooted'].containing_oneof = _FROMRADIO.oneofs_by_name['payloadVariant']
-_TORADIO_PEERINFO.containing_type = _TORADIO
-_TORADIO.fields_by_name['packet'].message_type = _MESHPACKET
-_TORADIO.fields_by_name['peer_info'].message_type = _TORADIO_PEERINFO
-_TORADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _TORADIO.fields_by_name['packet'])
-_TORADIO.fields_by_name['packet'].containing_oneof = _TORADIO.oneofs_by_name['payloadVariant']
-_TORADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _TORADIO.fields_by_name['peer_info'])
-_TORADIO.fields_by_name['peer_info'].containing_oneof = _TORADIO.oneofs_by_name['payloadVariant']
-_TORADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _TORADIO.fields_by_name['want_config_id'])
-_TORADIO.fields_by_name['want_config_id'].containing_oneof = _TORADIO.oneofs_by_name['payloadVariant']
-_TORADIO.oneofs_by_name['payloadVariant'].fields.append(
-  _TORADIO.fields_by_name['disconnect'])
-_TORADIO.fields_by_name['disconnect'].containing_oneof = _TORADIO.oneofs_by_name['payloadVariant']
-DESCRIPTOR.message_types_by_name['Position'] = _POSITION
-DESCRIPTOR.message_types_by_name['User'] = _USER
-DESCRIPTOR.message_types_by_name['RouteDiscovery'] = _ROUTEDISCOVERY
-DESCRIPTOR.message_types_by_name['Routing'] = _ROUTING
-DESCRIPTOR.message_types_by_name['Data'] = _DATA
-DESCRIPTOR.message_types_by_name['MeshPacket'] = _MESHPACKET
-DESCRIPTOR.message_types_by_name['NodeInfo'] = _NODEINFO
-DESCRIPTOR.message_types_by_name['MyNodeInfo'] = _MYNODEINFO
-DESCRIPTOR.message_types_by_name['LogRecord'] = _LOGRECORD
-DESCRIPTOR.message_types_by_name['FromRadio'] = _FROMRADIO
-DESCRIPTOR.message_types_by_name['ToRadio'] = _TORADIO
-DESCRIPTOR.enum_types_by_name['HardwareModel'] = _HARDWAREMODEL
-DESCRIPTOR.enum_types_by_name['Team'] = _TEAM
-DESCRIPTOR.enum_types_by_name['Constants'] = _CONSTANTS
-DESCRIPTOR.enum_types_by_name['CriticalErrorCode'] = _CRITICALERRORCODE
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-Position = _reflection.GeneratedProtocolMessageType('Position', (_message.Message,), {
-  'DESCRIPTOR' : _POSITION,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:Position)
-  })
-_sym_db.RegisterMessage(Position)
-
-User = _reflection.GeneratedProtocolMessageType('User', (_message.Message,), {
-  'DESCRIPTOR' : _USER,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:User)
-  })
-_sym_db.RegisterMessage(User)
-
-RouteDiscovery = _reflection.GeneratedProtocolMessageType('RouteDiscovery', (_message.Message,), {
-  'DESCRIPTOR' : _ROUTEDISCOVERY,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:RouteDiscovery)
-  })
-_sym_db.RegisterMessage(RouteDiscovery)
-
-Routing = _reflection.GeneratedProtocolMessageType('Routing', (_message.Message,), {
-  'DESCRIPTOR' : _ROUTING,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:Routing)
-  })
-_sym_db.RegisterMessage(Routing)
-
-Data = _reflection.GeneratedProtocolMessageType('Data', (_message.Message,), {
-  'DESCRIPTOR' : _DATA,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:Data)
-  })
-_sym_db.RegisterMessage(Data)
-
-MeshPacket = _reflection.GeneratedProtocolMessageType('MeshPacket', (_message.Message,), {
-  'DESCRIPTOR' : _MESHPACKET,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:MeshPacket)
-  })
-_sym_db.RegisterMessage(MeshPacket)
-
-NodeInfo = _reflection.GeneratedProtocolMessageType('NodeInfo', (_message.Message,), {
-  'DESCRIPTOR' : _NODEINFO,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:NodeInfo)
-  })
-_sym_db.RegisterMessage(NodeInfo)
-
-MyNodeInfo = _reflection.GeneratedProtocolMessageType('MyNodeInfo', (_message.Message,), {
-  'DESCRIPTOR' : _MYNODEINFO,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:MyNodeInfo)
-  })
-_sym_db.RegisterMessage(MyNodeInfo)
-
-LogRecord = _reflection.GeneratedProtocolMessageType('LogRecord', (_message.Message,), {
-  'DESCRIPTOR' : _LOGRECORD,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:LogRecord)
-  })
-_sym_db.RegisterMessage(LogRecord)
-
-FromRadio = _reflection.GeneratedProtocolMessageType('FromRadio', (_message.Message,), {
-  'DESCRIPTOR' : _FROMRADIO,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:FromRadio)
-  })
-_sym_db.RegisterMessage(FromRadio)
-
-ToRadio = _reflection.GeneratedProtocolMessageType('ToRadio', (_message.Message,), {
-
-  'PeerInfo' : _reflection.GeneratedProtocolMessageType('PeerInfo', (_message.Message,), {
-    'DESCRIPTOR' : _TORADIO_PEERINFO,
-    '__module__' : 'mesh_pb2'
-    # @@protoc_insertion_point(class_scope:ToRadio.PeerInfo)
-    })
-  ,
-  'DESCRIPTOR' : _TORADIO,
-  '__module__' : 'mesh_pb2'
-  # @@protoc_insertion_point(class_scope:ToRadio)
-  })
-_sym_db.RegisterMessage(ToRadio)
-_sym_db.RegisterMessage(ToRadio.PeerInfo)
-
-
-DESCRIPTOR._options = None
-_MYNODEINFO.fields_by_name['region']._options = None
-_MYNODEINFO.fields_by_name['hw_model_deprecated']._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Data -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var DEST_FIELD_NUMBER
-
-
-
-
var PAYLOAD_FIELD_NUMBER
-
-
-
-
var PORTNUM_FIELD_NUMBER
-
-
-
-
var REQUEST_ID_FIELD_NUMBER
-
-
-
-
var SOURCE_FIELD_NUMBER
-
-
-
-
var WANT_RESPONSE_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var dest
-
-

Getter for dest.

-
- -Expand source code - -
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)
-
-
-
var payload
-
-

Getter for payload.

-
- -Expand source code - -
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)
-
-
-
var portnum
-
-

Getter for portnum.

-
- -Expand source code - -
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)
-
-
-
var request_id
-
-

Getter for request_id.

-
- -Expand source code - -
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)
-
-
-
var source
-
-

Getter for source.

-
- -Expand source code - -
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)
-
-
-
var want_response
-
-

Getter for want_response.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class FromRadio -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var CONFIG_COMPLETE_ID_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
var LOG_RECORD_FIELD_NUMBER
-
-
-
-
var MY_INFO_FIELD_NUMBER
-
-
-
-
var NODE_INFO_FIELD_NUMBER
-
-
-
-
var NUM_FIELD_NUMBER
-
-
-
-
var PACKET_FIELD_NUMBER
-
-
-
-
var REBOOTED_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var config_complete_id
-
-

Getter for config_complete_id.

-
- -Expand source code - -
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)
-
-
-
var log_record
-
-

Getter for log_record.

-
- -Expand source code - -
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
-
-
-
var my_info
-
-

Getter for my_info.

-
- -Expand source code - -
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
-
-
-
var node_info
-
-

Getter for node_info.

-
- -Expand source code - -
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
-
-
-
var num
-
-

Getter for num.

-
- -Expand source code - -
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)
-
-
-
var packet
-
-

Getter for packet.

-
- -Expand source code - -
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
-
-
-
var rebooted
-
-

Getter for rebooted.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class LogRecord -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var CRITICAL
-
-
-
-
var DEBUG
-
-
-
-
var DESCRIPTOR
-
-
-
-
var ERROR
-
-
-
-
var INFO
-
-
-
-
var LEVEL_FIELD_NUMBER
-
-
-
-
var Level
-
-
-
-
var MESSAGE_FIELD_NUMBER
-
-
-
-
var SOURCE_FIELD_NUMBER
-
-
-
-
var TIME_FIELD_NUMBER
-
-
-
-
var TRACE
-
-
-
-
var UNSET
-
-
-
-
var WARNING
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var level
-
-

Getter for level.

-
- -Expand source code - -
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)
-
-
-
var message
-
-

Getter for message.

-
- -Expand source code - -
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)
-
-
-
var source
-
-

Getter for source.

-
- -Expand source code - -
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)
-
-
-
var time
-
-

Getter for time.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class MeshPacket -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var ACK
-
-
-
-
var BACKGROUND
-
-
-
-
var CHANNEL_FIELD_NUMBER
-
-
-
-
var DECODED_FIELD_NUMBER
-
-
-
-
var DEFAULT
-
-
-
-
var DELAYED_BROADCAST
-
-
-
-
var DELAYED_DIRECT
-
-
-
-
var DELAYED_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
var Delayed
-
-
-
-
var ENCRYPTED_FIELD_NUMBER
-
-
-
-
var FROM_FIELD_NUMBER
-
-
-
-
var HOP_LIMIT_FIELD_NUMBER
-
-
-
-
var ID_FIELD_NUMBER
-
-
-
-
var IS_TAPBACK_FIELD_NUMBER
-
-
-
-
var MAX
-
-
-
-
var MIN
-
-
-
-
var NO_DELAY
-
-
-
-
var PRIORITY_FIELD_NUMBER
-
-
-
-
var Priority
-
-
-
-
var RELIABLE
-
-
-
-
var REPLY_ID_FIELD_NUMBER
-
-
-
-
var RX_RSSI_FIELD_NUMBER
-
-
-
-
var RX_SNR_FIELD_NUMBER
-
-
-
-
var RX_TIME_FIELD_NUMBER
-
-
-
-
var TO_FIELD_NUMBER
-
-
-
-
var UNSET
-
-
-
-
var WANT_ACK_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var channel
-
-

Getter for channel.

-
- -Expand source code - -
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)
-
-
-
var decoded
-
-

Getter for decoded.

-
- -Expand source code - -
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
-
-
-
var delayed
-
-

Getter for delayed.

-
- -Expand source code - -
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)
-
-
-
var encrypted
-
-

Getter for encrypted.

-
- -Expand source code - -
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)
-
-
-
var from
-
-

Getter for from.

-
- -Expand source code - -
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)
-
-
-
var hop_limit
-
-

Getter for hop_limit.

-
- -Expand source code - -
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)
-
-
-
var id
-
-

Getter for id.

-
- -Expand source code - -
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)
-
-
-
var is_tapback
-
-

Getter for is_tapback.

-
- -Expand source code - -
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)
-
-
-
var priority
-
-

Getter for priority.

-
- -Expand source code - -
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)
-
-
-
var reply_id
-
-

Getter for reply_id.

-
- -Expand source code - -
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)
-
-
-
var rx_rssi
-
-

Getter for rx_rssi.

-
- -Expand source code - -
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)
-
-
-
var rx_snr
-
-

Getter for rx_snr.

-
- -Expand source code - -
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)
-
-
-
var rx_time
-
-

Getter for rx_time.

-
- -Expand source code - -
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)
-
-
-
var to
-
-

Getter for to.

-
- -Expand source code - -
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)
-
-
-
var want_ack
-
-

Getter for want_ack.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class MyNodeInfo -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var AIR_PERIOD_RX_FIELD_NUMBER
-
-
-
-
var AIR_PERIOD_TX_FIELD_NUMBER
-
-
-
-
var BITRATE_FIELD_NUMBER
-
-
-
-
var CHANNEL_UTILIZATION_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
var ERROR_ADDRESS_FIELD_NUMBER
-
-
-
-
var ERROR_CODE_FIELD_NUMBER
-
-
-
-
var ERROR_COUNT_FIELD_NUMBER
-
-
-
-
var FIRMWARE_VERSION_FIELD_NUMBER
-
-
-
-
var HAS_GPS_FIELD_NUMBER
-
-
-
-
var HAS_WIFI_FIELD_NUMBER
-
-
-
-
var HW_MODEL_DEPRECATED_FIELD_NUMBER
-
-
-
-
var MAX_CHANNELS_FIELD_NUMBER
-
-
-
-
var MESSAGE_TIMEOUT_MSEC_FIELD_NUMBER
-
-
-
-
var MIN_APP_VERSION_FIELD_NUMBER
-
-
-
-
var MY_NODE_NUM_FIELD_NUMBER
-
-
-
-
var NUM_BANDS_FIELD_NUMBER
-
-
-
-
var REBOOT_COUNT_FIELD_NUMBER
-
-
-
-
var REGION_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var air_period_rx
-
-

Getter for air_period_rx.

-
- -Expand source code - -
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
-
-
-
var air_period_tx
-
-

Getter for air_period_tx.

-
- -Expand source code - -
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
-
-
-
var bitrate
-
-

Getter for bitrate.

-
- -Expand source code - -
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)
-
-
-
var channel_utilization
-
-

Getter for channel_utilization.

-
- -Expand source code - -
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)
-
-
-
var error_address
-
-

Getter for error_address.

-
- -Expand source code - -
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)
-
-
-
var error_code
-
-

Getter for error_code.

-
- -Expand source code - -
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)
-
-
-
var error_count
-
-

Getter for error_count.

-
- -Expand source code - -
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)
-
-
-
var firmware_version
-
-

Getter for firmware_version.

-
- -Expand source code - -
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)
-
-
-
var has_gps
-
-

Getter for has_gps.

-
- -Expand source code - -
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)
-
-
-
var has_wifi
-
-

Getter for has_wifi.

-
- -Expand source code - -
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)
-
-
-
var hw_model_deprecated
-
-

Getter for hw_model_deprecated.

-
- -Expand source code - -
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)
-
-
-
var max_channels
-
-

Getter for max_channels.

-
- -Expand source code - -
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)
-
-
-
var message_timeout_msec
-
-

Getter for message_timeout_msec.

-
- -Expand source code - -
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)
-
-
-
var min_app_version
-
-

Getter for min_app_version.

-
- -Expand source code - -
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)
-
-
-
var my_node_num
-
-

Getter for my_node_num.

-
- -Expand source code - -
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)
-
-
-
var num_bands
-
-

Getter for num_bands.

-
- -Expand source code - -
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)
-
-
-
var reboot_count
-
-

Getter for reboot_count.

-
- -Expand source code - -
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)
-
-
-
var region
-
-

Getter for region.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class NodeInfo -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var LAST_HEARD_FIELD_NUMBER
-
-
-
-
var NUM_FIELD_NUMBER
-
-
-
-
var POSITION_FIELD_NUMBER
-
-
-
-
var SNR_FIELD_NUMBER
-
-
-
-
var USER_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var last_heard
-
-

Getter for last_heard.

-
- -Expand source code - -
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)
-
-
-
var num
-
-

Getter for num.

-
- -Expand source code - -
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)
-
-
-
var position
-
-

Getter for position.

-
- -Expand source code - -
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
-
-
-
var snr
-
-

Getter for snr.

-
- -Expand source code - -
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)
-
-
-
var user
-
-

Getter for user.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class Position -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var ALTITUDE_FIELD_NUMBER
-
-
-
-
var ALTITUDE_HAE_FIELD_NUMBER
-
-
-
-
var ALTITUDE_SOURCE_FIELD_NUMBER
-
-
-
-
var ALTSRC_BAROMETRIC
-
-
-
-
var ALTSRC_GPS_EXTERNAL
-
-
-
-
var ALTSRC_GPS_INTERNAL
-
-
-
-
var ALTSRC_MANUAL_ENTRY
-
-
-
-
var ALTSRC_UNSPECIFIED
-
-
-
-
var ALT_GEOID_SEP_FIELD_NUMBER
-
-
-
-
var AltSource
-
-
-
-
var BATTERY_LEVEL_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
var FIX_QUALITY_FIELD_NUMBER
-
-
-
-
var FIX_TYPE_FIELD_NUMBER
-
-
-
-
var GPS_ACCURACY_FIELD_NUMBER
-
-
-
-
var GROUND_SPEED_FIELD_NUMBER
-
-
-
-
var GROUND_TRACK_FIELD_NUMBER
-
-
-
-
var HDOP_FIELD_NUMBER
-
-
-
-
var LATITUDE_I_FIELD_NUMBER
-
-
-
-
var LOCATION_SOURCE_FIELD_NUMBER
-
-
-
-
var LOCSRC_GPS_EXTERNAL
-
-
-
-
var LOCSRC_GPS_INTERNAL
-
-
-
-
var LOCSRC_MANUAL_ENTRY
-
-
-
-
var LOCSRC_UNSPECIFIED
-
-
-
-
var LONGITUDE_I_FIELD_NUMBER
-
-
-
-
var LocSource
-
-
-
-
var PDOP_FIELD_NUMBER
-
-
-
-
var POS_NEXT_UPDATE_FIELD_NUMBER
-
-
-
-
var POS_SEQ_NUMBER_FIELD_NUMBER
-
-
-
-
var POS_TIMESTAMP_FIELD_NUMBER
-
-
-
-
var POS_TIME_MILLIS_FIELD_NUMBER
-
-
-
-
var SATS_IN_VIEW_FIELD_NUMBER
-
-
-
-
var SENSOR_ID_FIELD_NUMBER
-
-
-
-
var TIME_FIELD_NUMBER
-
-
-
-
var VDOP_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var HDOP
-
-

Getter for HDOP.

-
- -Expand source code - -
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)
-
-
-
var PDOP
-
-

Getter for PDOP.

-
- -Expand source code - -
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)
-
-
-
var VDOP
-
-

Getter for VDOP.

-
- -Expand source code - -
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)
-
-
-
var alt_geoid_sep
-
-

Getter for alt_geoid_sep.

-
- -Expand source code - -
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)
-
-
-
var altitude
-
-

Getter for altitude.

-
- -Expand source code - -
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)
-
-
-
var altitude_hae
-
-

Getter for altitude_hae.

-
- -Expand source code - -
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)
-
-
-
var altitude_source
-
-

Getter for altitude_source.

-
- -Expand source code - -
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)
-
-
-
var battery_level
-
-

Getter for battery_level.

-
- -Expand source code - -
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)
-
-
-
var fix_quality
-
-

Getter for fix_quality.

-
- -Expand source code - -
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)
-
-
-
var fix_type
-
-

Getter for fix_type.

-
- -Expand source code - -
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)
-
-
-
var gps_accuracy
-
-

Getter for gps_accuracy.

-
- -Expand source code - -
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)
-
-
-
var ground_speed
-
-

Getter for ground_speed.

-
- -Expand source code - -
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)
-
-
-
var ground_track
-
-

Getter for ground_track.

-
- -Expand source code - -
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)
-
-
-
var latitude_i
-
-

Getter for latitude_i.

-
- -Expand source code - -
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)
-
-
-
var location_source
-
-

Getter for location_source.

-
- -Expand source code - -
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)
-
-
-
var longitude_i
-
-

Getter for longitude_i.

-
- -Expand source code - -
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)
-
-
-
var pos_next_update
-
-

Getter for pos_next_update.

-
- -Expand source code - -
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)
-
-
-
var pos_seq_number
-
-

Getter for pos_seq_number.

-
- -Expand source code - -
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)
-
-
-
var pos_time_millis
-
-

Getter for pos_time_millis.

-
- -Expand source code - -
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)
-
-
-
var pos_timestamp
-
-

Getter for pos_timestamp.

-
- -Expand source code - -
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)
-
-
-
var sats_in_view
-
-

Getter for sats_in_view.

-
- -Expand source code - -
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)
-
-
-
var sensor_id
-
-

Getter for sensor_id.

-
- -Expand source code - -
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)
-
-
-
var time
-
-

Getter for time.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class RouteDiscovery -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var ROUTE_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var route
-
-

Getter for route.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class Routing -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var BAD_REQUEST
-
-
-
-
var DESCRIPTOR
-
-
-
-
var ERROR_REASON_FIELD_NUMBER
-
-
-
-
var Error
-
-
-
-
var GOT_NAK
-
-
-
-
var MAX_RETRANSMIT
-
-
-
-
var NONE
-
-
-
-
var NOT_AUTHORIZED
-
-
-
-
var NO_CHANNEL
-
-
-
-
var NO_INTERFACE
-
-
-
-
var NO_RESPONSE
-
-
-
-
var NO_ROUTE
-
-
-
-
var ROUTE_REPLY_FIELD_NUMBER
-
-
-
-
var ROUTE_REQUEST_FIELD_NUMBER
-
-
-
-
var TIMEOUT
-
-
-
-
var TOO_LARGE
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var error_reason
-
-

Getter for error_reason.

-
- -Expand source code - -
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)
-
-
-
var route_reply
-
-

Getter for route_reply.

-
- -Expand source code - -
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
-
-
-
var route_request
-
-

Getter for route_request.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class ToRadio -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var DISCONNECT_FIELD_NUMBER
-
-
-
-
var PACKET_FIELD_NUMBER
-
-
-
-
var PEER_INFO_FIELD_NUMBER
-
-
-
-
var PeerInfo
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-
-
var WANT_CONFIG_ID_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var disconnect
-
-

Getter for disconnect.

-
- -Expand source code - -
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)
-
-
-
var packet
-
-

Getter for packet.

-
- -Expand source code - -
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
-
-
-
var peer_info
-
-

Getter for peer_info.

-
- -Expand source code - -
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
-
-
-
var want_config_id
-
-

Getter for want_config_id.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class User -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var ANT_AZIMUTH_FIELD_NUMBER
-
-
-
-
var ANT_GAIN_DBI_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
var HW_MODEL_FIELD_NUMBER
-
-
-
-
var ID_FIELD_NUMBER
-
-
-
-
var IS_LICENSED_FIELD_NUMBER
-
-
-
-
var LONG_NAME_FIELD_NUMBER
-
-
-
-
var MACADDR_FIELD_NUMBER
-
-
-
-
var SHORT_NAME_FIELD_NUMBER
-
-
-
-
var TEAM_FIELD_NUMBER
-
-
-
-
var TX_POWER_DBM_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var ant_azimuth
-
-

Getter for ant_azimuth.

-
- -Expand source code - -
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)
-
-
-
var ant_gain_dbi
-
-

Getter for ant_gain_dbi.

-
- -Expand source code - -
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)
-
-
-
var hw_model
-
-

Getter for hw_model.

-
- -Expand source code - -
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)
-
-
-
var id
-
-

Getter for id.

-
- -Expand source code - -
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)
-
-
-
var is_licensed
-
-

Getter for is_licensed.

-
- -Expand source code - -
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)
-
-
-
var long_name
-
-

Getter for long_name.

-
- -Expand source code - -
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)
-
-
-
var macaddr
-
-

Getter for macaddr.

-
- -Expand source code - -
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)
-
-
-
var short_name
-
-

Getter for short_name.

-
- -Expand source code - -
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)
-
-
-
var team
-
-

Getter for team.

-
- -Expand source code - -
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)
-
-
-
var tx_power_dbm
-
-

Getter for tx_power_dbm.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/mqtt_pb2.html b/docs/meshtastic/mqtt_pb2.html deleted file mode 100644 index c18a637..0000000 --- a/docs/meshtastic/mqtt_pb2.html +++ /dev/null @@ -1,759 +0,0 @@ - - - - - - -meshtastic.mqtt_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.mqtt_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: mqtt.proto
-
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-from . import mesh_pb2 as mesh__pb2
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='mqtt.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\nMQTTProtosH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\nmqtt.proto\x1a\nmesh.proto\"V\n\x0fServiceEnvelope\x12\x1b\n\x06packet\x18\x01 \x01(\x0b\x32\x0b.MeshPacket\x12\x12\n\nchannel_id\x18\x02 \x01(\t\x12\x12\n\ngateway_id\x18\x03 \x01(\tBF\n\x13\x63om.geeksville.meshB\nMQTTProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-  ,
-  dependencies=[mesh__pb2.DESCRIPTOR,])
-
-
-
-
-_SERVICEENVELOPE = _descriptor.Descriptor(
-  name='ServiceEnvelope',
-  full_name='ServiceEnvelope',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='packet', full_name='ServiceEnvelope.packet', index=0,
-      number=1, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='channel_id', full_name='ServiceEnvelope.channel_id', index=1,
-      number=2, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gateway_id', full_name='ServiceEnvelope.gateway_id', index=2,
-      number=3, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=26,
-  serialized_end=112,
-)
-
-_SERVICEENVELOPE.fields_by_name['packet'].message_type = mesh__pb2._MESHPACKET
-DESCRIPTOR.message_types_by_name['ServiceEnvelope'] = _SERVICEENVELOPE
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-ServiceEnvelope = _reflection.GeneratedProtocolMessageType('ServiceEnvelope', (_message.Message,), {
-  'DESCRIPTOR' : _SERVICEENVELOPE,
-  '__module__' : 'mqtt_pb2'
-  # @@protoc_insertion_point(class_scope:ServiceEnvelope)
-  })
-_sym_db.RegisterMessage(ServiceEnvelope)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class ServiceEnvelope -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var CHANNEL_ID_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
var GATEWAY_ID_FIELD_NUMBER
-
-
-
-
var PACKET_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var channel_id
-
-

Getter for channel_id.

-
- -Expand source code - -
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)
-
-
-
var gateway_id
-
-

Getter for gateway_id.

-
- -Expand source code - -
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)
-
-
-
var packet
-
-

Getter for packet.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/node.html b/docs/meshtastic/node.html deleted file mode 100644 index b0a7365..0000000 --- a/docs/meshtastic/node.html +++ /dev/null @@ -1,1280 +0,0 @@ - - - - - - -meshtastic.node API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.node

-
-
-

Node class

-
- -Expand source code - -
"""Node class
-"""
-
-import logging
-import base64
-from google.protobuf.json_format import MessageToJson
-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, noProto=False):
-        """Constructor"""
-        self.iface = iface
-        self.nodeNum = nodeNum
-        self.radioConfig = None
-        self.channels = None
-        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:
-                    print(f"  {channel_pb2.Channel.Role.Name(c.role)} psk={pskToString(c.settings.psk)} {cStr}")
-        publicURL = self.getURL(includeAll=False)
-        adminURL = self.getURL(includeAll=True)
-        print(f"\nPrimary channel URL: {publicURL}")
-        if adminURL != publicURL:
-            print(f"Complete URL (includes all channels): {adminURL}")
-
-    def showInfo(self):
-        """Show human readable description of our node"""
-        prefs = ""
-        if self.radioConfig and self.radioConfig.preferences:
-            prefs = stripnl(MessageToJson(self.radioConfig.preferences))
-        print(f"Preferences: {prefs}\n")
-        self.showChannels()
-
-    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
-
-        self._requestSettings()
-
-    def turnOffEncryptionOnPrimaryChannel(self):
-        """Turn off encryption on primary channel."""
-        self.channels[0].settings.psk = fromPSK("none")
-        print("Writing modified channels to device")
-        self.writeChannel(0)
-
-    def waitForConfig(self):
-        """Block until radio config is received. Returns True if config has been received."""
-        return self._timeout.waitForSet(self, attrs=('radioConfig', 'channels'))
-
-    def writeConfig(self):
-        """Write the current (edited) radioConfig to the device"""
-        if self.radioConfig is None:
-            our_exit("Error: No RadioConfig has been read")
-
-        p = admin_pb2.AdminMessage()
-        p.set_radio.CopyFrom(self.radioConfig)
-
-        self._sendAdmin(p)
-        logging.debug("Wrote config")
-
-    def writeChannel(self, channelIndex, adminIndex=0):
-        """Write the current (edited) channel to the device"""
-
-        p = admin_pb2.AdminMessage()
-        p.set_channel.CopyFrom(self.channels[channelIndex])
-
-        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]
-        if ch.role not in (channel_pb2.Channel.Role.SECONDARY, channel_pb2.Channel.Role.DISABLED):
-            our_exit("Warning: Only SECONDARY channels can be deleted")
-
-        # we are careful here because if we move the "admin" channel the channelIndex we need to use
-        # for sending admin channels will also change
-        adminIndex = self.iface.localNode._getAdminChannelIndex()
-
-        self.channels.pop(channelIndex)
-        self._fixupChannels()  # expand back to 8 channels
-
-        index = channelIndex
-        while index < self.iface.myInfo.max_channels:
-            self.writeChannel(index, adminIndex=adminIndex)
-            index += 1
-
-            # if we are updating the local node, we might end up
-            # *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 written it), so we can start finding it by name again
-                adminIndex = 0
-
-    def getChannelByName(self, name):
-        """Try to find the named channel or return None"""
-        for c in (self.channels or []):
-            if c.settings and c.settings.name == name:
-                return c
-        return None
-
-    def getDisabledChannel(self):
-        """Return the first channel that is disabled (i.e. available for some new use)"""
-        for c in self.channels:
-            if c.role == channel_pb2.Channel.Role.DISABLED:
-                return c
-        return None
-
-    def _getAdminChannelIndex(self):
-        """Return the channel number of the admin channel, or 0 if no reserved channel"""
-        c = self.getChannelByName("admin")
-        if c:
-            return c.index
-        else:
-            return 0
-
-    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:
-            long_name = long_name.strip()
-            if short_name is None:
-                words = long_name.split()
-                if len(long_name) <= nChars:
-                    short_name = long_name
-                elif len(words) >= minChars:
-                    short_name = ''.join(map(lambda word: word[0], words))
-                else:
-                    trans = str.maketrans(dict.fromkeys('aeiouAEIOU'))
-                    short_name = long_name[0] + long_name[1:].translate(trans)
-                    if len(short_name) < nChars:
-                        short_name = long_name[:nChars]
-
-        p = admin_pb2.AdminMessage()
-
-        if long_name is not None:
-            p.set_owner.long_name = long_name
-        if short_name is not None:
-            short_name = short_name.strip()
-            if len(short_name) > nChars:
-                short_name = short_name[:nChars]
-            p.set_owner.short_name = short_name
-            p.set_owner.is_licensed = is_licensed
-        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):
-        """The sharable URL that describes the current channel"""
-        # Only keep the primary/secondary channels, assume primary is first
-        channelSet = apponly_pb2.ChannelSet()
-        if self.channels:
-            for c in self.channels:
-                if c.role == channel_pb2.Channel.Role.PRIMARY or (includeAll and c.role == channel_pb2.Channel.Role.SECONDARY):
-                    channelSet.settings.append(c.settings)
-        some_bytes = channelSet.SerializeToString()
-        s = base64.urlsafe_b64encode(some_bytes).decode('ascii')
-        return f"https://www.meshtastic.org/d/#{s}".replace("=", "")
-
-    def setURL(self, url):
-        """Set mesh network URL"""
-        if self.radioConfig is None:
-            our_exit("Warning: No RadioConfig has been read")
-
-        # URLs are of the form https://www.meshtastic.org/d/#{base64_channel_set}
-        # Split on '/#' to find the base64 encoded channel settings
-        splitURL = url.split("/#")
-        b64 = splitURL[-1]
-
-        # We normally strip padding to make for a shorter URL, but the python parser doesn't like
-        # that.  So add back any missing padding
-        # per https://stackoverflow.com/a/9807138
-        missing_padding = len(b64) % 4
-        if missing_padding:
-            b64 += '=' * (4 - missing_padding)
-
-        decodedURL = base64.urlsafe_b64decode(b64)
-        channelSet = apponly_pb2.ChannelSet()
-        channelSet.ParseFromString(decodedURL)
-
-
-        if len(channelSet.settings) == 0:
-            our_exit("Warning: There were no settings.")
-
-        i = 0
-        for chs in channelSet.settings:
-            ch = channel_pb2.Channel()
-            ch.role = channel_pb2.Channel.Role.PRIMARY if i == 0 else channel_pb2.Channel.Role.SECONDARY
-            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
-
-        # Show progress message for super slow operations
-        if self != self.iface.localNode:
-            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=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)
-
-    def reboot(self, secs: int = 10):
-        """Tell the node to reboot."""
-        p = admin_pb2.AdminMessage()
-        p.reboot_seconds = secs
-        logging.info(f"Telling node to reboot in {secs} seconds")
-
-        return self._sendAdmin(p)
-
-    def _fixupChannels(self):
-        """Fixup indexes and add disabled channels as needed"""
-
-        # Add extra disabled channels as needed
-        # TODO: These 2 lines seem to not do anything.
-        for index, ch in enumerate(self.channels):
-            ch.index = index  # fixup indexes
-
-        self._fillChannels()
-
-    def _fillChannels(self):
-        """Mark unused channels as disabled"""
-
-        # Add extra disabled channels as needed
-        index = len(self.channels)
-        while index < self.iface.myInfo.max_channels:
-            ch = channel_pb2.Channel()
-            ch.role = channel_pb2.Channel.Role.DISABLED
-            ch.index = index
-            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"""
-        p = admin_pb2.AdminMessage()
-        p.get_channel_request = channelNum + 1
-
-        # Show progress message for super slow operations
-        if self != self.iface.localNode:
-            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}")
-
-        return self._sendAdmin(p, wantResponse=True, onResponse=self.onResponseRequestChannel)
-
-
-    # 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 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)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Node -(iface, nodeNum, noProto=False) -
-
-

A model of a (local or remote) node in the mesh

-

Includes methods for radioConfig and channels

-

Constructor

-
- -Expand source code - -
class Node:
-    """A model of a (local or remote) node in the mesh
-
-    Includes methods for radioConfig and channels
-    """
-
-    def __init__(self, iface, nodeNum, noProto=False):
-        """Constructor"""
-        self.iface = iface
-        self.nodeNum = nodeNum
-        self.radioConfig = None
-        self.channels = None
-        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:
-                    print(f"  {channel_pb2.Channel.Role.Name(c.role)} psk={pskToString(c.settings.psk)} {cStr}")
-        publicURL = self.getURL(includeAll=False)
-        adminURL = self.getURL(includeAll=True)
-        print(f"\nPrimary channel URL: {publicURL}")
-        if adminURL != publicURL:
-            print(f"Complete URL (includes all channels): {adminURL}")
-
-    def showInfo(self):
-        """Show human readable description of our node"""
-        prefs = ""
-        if self.radioConfig and self.radioConfig.preferences:
-            prefs = stripnl(MessageToJson(self.radioConfig.preferences))
-        print(f"Preferences: {prefs}\n")
-        self.showChannels()
-
-    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
-
-        self._requestSettings()
-
-    def turnOffEncryptionOnPrimaryChannel(self):
-        """Turn off encryption on primary channel."""
-        self.channels[0].settings.psk = fromPSK("none")
-        print("Writing modified channels to device")
-        self.writeChannel(0)
-
-    def waitForConfig(self):
-        """Block until radio config is received. Returns True if config has been received."""
-        return self._timeout.waitForSet(self, attrs=('radioConfig', 'channels'))
-
-    def writeConfig(self):
-        """Write the current (edited) radioConfig to the device"""
-        if self.radioConfig is None:
-            our_exit("Error: No RadioConfig has been read")
-
-        p = admin_pb2.AdminMessage()
-        p.set_radio.CopyFrom(self.radioConfig)
-
-        self._sendAdmin(p)
-        logging.debug("Wrote config")
-
-    def writeChannel(self, channelIndex, adminIndex=0):
-        """Write the current (edited) channel to the device"""
-
-        p = admin_pb2.AdminMessage()
-        p.set_channel.CopyFrom(self.channels[channelIndex])
-
-        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]
-        if ch.role not in (channel_pb2.Channel.Role.SECONDARY, channel_pb2.Channel.Role.DISABLED):
-            our_exit("Warning: Only SECONDARY channels can be deleted")
-
-        # we are careful here because if we move the "admin" channel the channelIndex we need to use
-        # for sending admin channels will also change
-        adminIndex = self.iface.localNode._getAdminChannelIndex()
-
-        self.channels.pop(channelIndex)
-        self._fixupChannels()  # expand back to 8 channels
-
-        index = channelIndex
-        while index < self.iface.myInfo.max_channels:
-            self.writeChannel(index, adminIndex=adminIndex)
-            index += 1
-
-            # if we are updating the local node, we might end up
-            # *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 written it), so we can start finding it by name again
-                adminIndex = 0
-
-    def getChannelByName(self, name):
-        """Try to find the named channel or return None"""
-        for c in (self.channels or []):
-            if c.settings and c.settings.name == name:
-                return c
-        return None
-
-    def getDisabledChannel(self):
-        """Return the first channel that is disabled (i.e. available for some new use)"""
-        for c in self.channels:
-            if c.role == channel_pb2.Channel.Role.DISABLED:
-                return c
-        return None
-
-    def _getAdminChannelIndex(self):
-        """Return the channel number of the admin channel, or 0 if no reserved channel"""
-        c = self.getChannelByName("admin")
-        if c:
-            return c.index
-        else:
-            return 0
-
-    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:
-            long_name = long_name.strip()
-            if short_name is None:
-                words = long_name.split()
-                if len(long_name) <= nChars:
-                    short_name = long_name
-                elif len(words) >= minChars:
-                    short_name = ''.join(map(lambda word: word[0], words))
-                else:
-                    trans = str.maketrans(dict.fromkeys('aeiouAEIOU'))
-                    short_name = long_name[0] + long_name[1:].translate(trans)
-                    if len(short_name) < nChars:
-                        short_name = long_name[:nChars]
-
-        p = admin_pb2.AdminMessage()
-
-        if long_name is not None:
-            p.set_owner.long_name = long_name
-        if short_name is not None:
-            short_name = short_name.strip()
-            if len(short_name) > nChars:
-                short_name = short_name[:nChars]
-            p.set_owner.short_name = short_name
-            p.set_owner.is_licensed = is_licensed
-        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):
-        """The sharable URL that describes the current channel"""
-        # Only keep the primary/secondary channels, assume primary is first
-        channelSet = apponly_pb2.ChannelSet()
-        if self.channels:
-            for c in self.channels:
-                if c.role == channel_pb2.Channel.Role.PRIMARY or (includeAll and c.role == channel_pb2.Channel.Role.SECONDARY):
-                    channelSet.settings.append(c.settings)
-        some_bytes = channelSet.SerializeToString()
-        s = base64.urlsafe_b64encode(some_bytes).decode('ascii')
-        return f"https://www.meshtastic.org/d/#{s}".replace("=", "")
-
-    def setURL(self, url):
-        """Set mesh network URL"""
-        if self.radioConfig is None:
-            our_exit("Warning: No RadioConfig has been read")
-
-        # URLs are of the form https://www.meshtastic.org/d/#{base64_channel_set}
-        # Split on '/#' to find the base64 encoded channel settings
-        splitURL = url.split("/#")
-        b64 = splitURL[-1]
-
-        # We normally strip padding to make for a shorter URL, but the python parser doesn't like
-        # that.  So add back any missing padding
-        # per https://stackoverflow.com/a/9807138
-        missing_padding = len(b64) % 4
-        if missing_padding:
-            b64 += '=' * (4 - missing_padding)
-
-        decodedURL = base64.urlsafe_b64decode(b64)
-        channelSet = apponly_pb2.ChannelSet()
-        channelSet.ParseFromString(decodedURL)
-
-
-        if len(channelSet.settings) == 0:
-            our_exit("Warning: There were no settings.")
-
-        i = 0
-        for chs in channelSet.settings:
-            ch = channel_pb2.Channel()
-            ch.role = channel_pb2.Channel.Role.PRIMARY if i == 0 else channel_pb2.Channel.Role.SECONDARY
-            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
-
-        # Show progress message for super slow operations
-        if self != self.iface.localNode:
-            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=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)
-
-    def reboot(self, secs: int = 10):
-        """Tell the node to reboot."""
-        p = admin_pb2.AdminMessage()
-        p.reboot_seconds = secs
-        logging.info(f"Telling node to reboot in {secs} seconds")
-
-        return self._sendAdmin(p)
-
-    def _fixupChannels(self):
-        """Fixup indexes and add disabled channels as needed"""
-
-        # Add extra disabled channels as needed
-        # TODO: These 2 lines seem to not do anything.
-        for index, ch in enumerate(self.channels):
-            ch.index = index  # fixup indexes
-
-        self._fillChannels()
-
-    def _fillChannels(self):
-        """Mark unused channels as disabled"""
-
-        # Add extra disabled channels as needed
-        index = len(self.channels)
-        while index < self.iface.myInfo.max_channels:
-            ch = channel_pb2.Channel()
-            ch.role = channel_pb2.Channel.Role.DISABLED
-            ch.index = index
-            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"""
-        p = admin_pb2.AdminMessage()
-        p.get_channel_request = channelNum + 1
-
-        # Show progress message for super slow operations
-        if self != self.iface.localNode:
-            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}")
-
-        return self._sendAdmin(p, wantResponse=True, onResponse=self.onResponseRequestChannel)
-
-
-    # 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 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)
-
-

Methods

-
-
-def deleteChannel(self, channelIndex) -
-
-

Delete the specifed channelIndex and shift other channels up

-
- -Expand source code - -
def deleteChannel(self, channelIndex):
-    """Delete the specifed channelIndex and shift other channels up"""
-    ch = self.channels[channelIndex]
-    if ch.role not in (channel_pb2.Channel.Role.SECONDARY, channel_pb2.Channel.Role.DISABLED):
-        our_exit("Warning: Only SECONDARY channels can be deleted")
-
-    # we are careful here because if we move the "admin" channel the channelIndex we need to use
-    # for sending admin channels will also change
-    adminIndex = self.iface.localNode._getAdminChannelIndex()
-
-    self.channels.pop(channelIndex)
-    self._fixupChannels()  # expand back to 8 channels
-
-    index = channelIndex
-    while index < self.iface.myInfo.max_channels:
-        self.writeChannel(index, adminIndex=adminIndex)
-        index += 1
-
-        # if we are updating the local node, we might end up
-        # *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 written it), so we can start finding it by name again
-            adminIndex = 0
-
-
-
-def exitSimulator(self) -
-
-

Tell a simulator node to exit (this message -is ignored for other nodes)

-
- -Expand source code - -
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)
-
-
-
-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

-
- -Expand source code - -
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 getChannelByName(self, name) -
-
-

Try to find the named channel or return None

-
- -Expand source code - -
def getChannelByName(self, name):
-    """Try to find the named channel or return None"""
-    for c in (self.channels or []):
-        if c.settings and c.settings.name == name:
-            return c
-    return None
-
-
-
-def getDisabledChannel(self) -
-
-

Return the first channel that is disabled (i.e. available for some new use)

-
- -Expand source code - -
def getDisabledChannel(self):
-    """Return the first channel that is disabled (i.e. available for some new use)"""
-    for c in self.channels:
-        if c.role == channel_pb2.Channel.Role.DISABLED:
-            return c
-    return None
-
-
-
-def getURL(self, includeAll: bool = True) -
-
-

The sharable URL that describes the current channel

-
- -Expand source code - -
def getURL(self, includeAll: bool = True):
-    """The sharable URL that describes the current channel"""
-    # Only keep the primary/secondary channels, assume primary is first
-    channelSet = apponly_pb2.ChannelSet()
-    if self.channels:
-        for c in self.channels:
-            if c.role == channel_pb2.Channel.Role.PRIMARY or (includeAll and c.role == channel_pb2.Channel.Role.SECONDARY):
-                channelSet.settings.append(c.settings)
-    some_bytes = channelSet.SerializeToString()
-    s = base64.urlsafe_b64encode(some_bytes).decode('ascii')
-    return f"https://www.meshtastic.org/d/#{s}".replace("=", "")
-
-
-
-def onResponseRequestChannel(self, p) -
-
-

Handle the response packet for requesting a channel _requestChannel()

-
- -Expand source code - -
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 onResponseRequestSettings(self, p) -
-
-

Handle the response packet for requesting settings _requestSettings()

-
- -Expand source code - -
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 reboot(self, secs: int = 10) -
-
-

Tell the node to reboot.

-
- -Expand source code - -
def reboot(self, secs: int = 10):
-    """Tell the node to reboot."""
-    p = admin_pb2.AdminMessage()
-    p.reboot_seconds = secs
-    logging.info(f"Telling node to reboot in {secs} seconds")
-
-    return self._sendAdmin(p)
-
-
-
-def requestConfig(self) -
-
-

Send regular MeshPackets to ask for settings and channels.

-
- -Expand source code - -
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
-
-    self._requestSettings()
-
-
-
-def setOwner(self, long_name=None, short_name=None, is_licensed=False, team=None) -
-
-

Set device owner name

-
- -Expand source code - -
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:
-        long_name = long_name.strip()
-        if short_name is None:
-            words = long_name.split()
-            if len(long_name) <= nChars:
-                short_name = long_name
-            elif len(words) >= minChars:
-                short_name = ''.join(map(lambda word: word[0], words))
-            else:
-                trans = str.maketrans(dict.fromkeys('aeiouAEIOU'))
-                short_name = long_name[0] + long_name[1:].translate(trans)
-                if len(short_name) < nChars:
-                    short_name = long_name[:nChars]
-
-    p = admin_pb2.AdminMessage()
-
-    if long_name is not None:
-        p.set_owner.long_name = long_name
-    if short_name is not None:
-        short_name = short_name.strip()
-        if len(short_name) > nChars:
-            short_name = short_name[:nChars]
-        p.set_owner.short_name = short_name
-        p.set_owner.is_licensed = is_licensed
-    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 setURL(self, url) -
-
-

Set mesh network URL

-
- -Expand source code - -
def setURL(self, url):
-    """Set mesh network URL"""
-    if self.radioConfig is None:
-        our_exit("Warning: No RadioConfig has been read")
-
-    # URLs are of the form https://www.meshtastic.org/d/#{base64_channel_set}
-    # Split on '/#' to find the base64 encoded channel settings
-    splitURL = url.split("/#")
-    b64 = splitURL[-1]
-
-    # We normally strip padding to make for a shorter URL, but the python parser doesn't like
-    # that.  So add back any missing padding
-    # per https://stackoverflow.com/a/9807138
-    missing_padding = len(b64) % 4
-    if missing_padding:
-        b64 += '=' * (4 - missing_padding)
-
-    decodedURL = base64.urlsafe_b64decode(b64)
-    channelSet = apponly_pb2.ChannelSet()
-    channelSet.ParseFromString(decodedURL)
-
-
-    if len(channelSet.settings) == 0:
-        our_exit("Warning: There were no settings.")
-
-    i = 0
-    for chs in channelSet.settings:
-        ch = channel_pb2.Channel()
-        ch.role = channel_pb2.Channel.Role.PRIMARY if i == 0 else channel_pb2.Channel.Role.SECONDARY
-        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 showChannels(self) -
-
-

Show human readable description of our channels.

-
- -Expand source code - -
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:
-                print(f"  {channel_pb2.Channel.Role.Name(c.role)} psk={pskToString(c.settings.psk)} {cStr}")
-    publicURL = self.getURL(includeAll=False)
-    adminURL = self.getURL(includeAll=True)
-    print(f"\nPrimary channel URL: {publicURL}")
-    if adminURL != publicURL:
-        print(f"Complete URL (includes all channels): {adminURL}")
-
-
-
-def showInfo(self) -
-
-

Show human readable description of our node

-
- -Expand source code - -
def showInfo(self):
-    """Show human readable description of our node"""
-    prefs = ""
-    if self.radioConfig and self.radioConfig.preferences:
-        prefs = stripnl(MessageToJson(self.radioConfig.preferences))
-    print(f"Preferences: {prefs}\n")
-    self.showChannels()
-
-
-
-def turnOffEncryptionOnPrimaryChannel(self) -
-
-

Turn off encryption on primary channel.

-
- -Expand source code - -
def turnOffEncryptionOnPrimaryChannel(self):
-    """Turn off encryption on primary channel."""
-    self.channels[0].settings.psk = fromPSK("none")
-    print("Writing modified channels to device")
-    self.writeChannel(0)
-
-
-
-def waitForConfig(self) -
-
-

Block until radio config is received. Returns True if config has been received.

-
- -Expand source code - -
def waitForConfig(self):
-    """Block until radio config is received. Returns True if config has been received."""
-    return self._timeout.waitForSet(self, attrs=('radioConfig', 'channels'))
-
-
-
-def writeChannel(self, channelIndex, adminIndex=0) -
-
-

Write the current (edited) channel to the device

-
- -Expand source code - -
def writeChannel(self, channelIndex, adminIndex=0):
-    """Write the current (edited) channel to the device"""
-
-    p = admin_pb2.AdminMessage()
-    p.set_channel.CopyFrom(self.channels[channelIndex])
-
-    self._sendAdmin(p, adminIndex=adminIndex)
-    logging.debug(f"Wrote channel {channelIndex}")
-
-
-
-def writeConfig(self) -
-
-

Write the current (edited) radioConfig to the device

-
- -Expand source code - -
def writeConfig(self):
-    """Write the current (edited) radioConfig to the device"""
-    if self.radioConfig is None:
-        our_exit("Error: No RadioConfig has been read")
-
-    p = admin_pb2.AdminMessage()
-    p.set_radio.CopyFrom(self.radioConfig)
-
-    self._sendAdmin(p)
-    logging.debug("Wrote config")
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/portnums_pb2.html b/docs/meshtastic/portnums_pb2.html deleted file mode 100644 index ee0c742..0000000 --- a/docs/meshtastic/portnums_pb2.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - -meshtastic.portnums_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.portnums_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: portnums.proto
-
-from google.protobuf.internal import enum_type_wrapper
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='portnums.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\010PortnumsH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\x0eportnums.proto*\xcb\x02\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12!\n\x1d\x45NVIRONMENTAL_MEASUREMENT_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42\x44\n\x13\x63om.geeksville.meshB\x08PortnumsH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-)
-
-_PORTNUM = _descriptor.EnumDescriptor(
-  name='PortNum',
-  full_name='PortNum',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='UNKNOWN_APP', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TEXT_MESSAGE_APP', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='REMOTE_HARDWARE_APP', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POSITION_APP', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='NODEINFO_APP', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ROUTING_APP', index=5, number=5,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ADMIN_APP', index=6, number=6,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='REPLY_APP', index=7, number=32,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='IP_TUNNEL_APP', index=8, number=33,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='SERIAL_APP', index=9, number=64,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='STORE_FORWARD_APP', index=10, number=65,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='RANGE_TEST_APP', index=11, number=66,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ENVIRONMENTAL_MEASUREMENT_APP', index=12, number=67,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ZPS_APP', index=13, number=68,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='PRIVATE_APP', index=14, number=256,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ATAK_FORWARDER', index=15, number=257,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MAX', index=16, number=511,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=19,
-  serialized_end=350,
-)
-_sym_db.RegisterEnumDescriptor(_PORTNUM)
-
-PortNum = enum_type_wrapper.EnumTypeWrapper(_PORTNUM)
-UNKNOWN_APP = 0
-TEXT_MESSAGE_APP = 1
-REMOTE_HARDWARE_APP = 2
-POSITION_APP = 3
-NODEINFO_APP = 4
-ROUTING_APP = 5
-ADMIN_APP = 6
-REPLY_APP = 32
-IP_TUNNEL_APP = 33
-SERIAL_APP = 64
-STORE_FORWARD_APP = 65
-RANGE_TEST_APP = 66
-ENVIRONMENTAL_MEASUREMENT_APP = 67
-ZPS_APP = 68
-PRIVATE_APP = 256
-ATAK_FORWARDER = 257
-MAX = 511
-
-
-DESCRIPTOR.enum_types_by_name['PortNum'] = _PORTNUM
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/radioconfig_pb2.html b/docs/meshtastic/radioconfig_pb2.html deleted file mode 100644 index a0de023..0000000 --- a/docs/meshtastic/radioconfig_pb2.html +++ /dev/null @@ -1,1604 +0,0 @@ - - - - - - -meshtastic.radioconfig_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.radioconfig_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: radioconfig.proto
-
-from google.protobuf.internal import enum_type_wrapper
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='radioconfig.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\021RadioConfigProtosH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\x11radioconfig.proto\"\xe7\x13\n\x0bRadioConfig\x12\x31\n\x0bpreferences\x18\x01 \x01(\x0b\x32\x1c.RadioConfig.UserPreferences\x1a\xa4\x13\n\x0fUserPreferences\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12 \n\x18position_broadcast_smart\x18\x11 \x01(\x08\x12\x1b\n\x13send_owner_interval\x18\x02 \x01(\r\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x16\n\x0escreen_on_secs\x18\x05 \x01(\r\x12\x1a\n\x12phone_timeout_secs\x18\x06 \x01(\r\x12\x1d\n\x15phone_sds_timeout_sec\x18\x07 \x01(\r\x12\x1d\n\x15mesh_sds_timeout_secs\x18\x08 \x01(\r\x12\x10\n\x08sds_secs\x18\t \x01(\r\x12\x0f\n\x07ls_secs\x18\n \x01(\r\x12\x15\n\rmin_wake_secs\x18\x0b \x01(\r\x12\x11\n\twifi_ssid\x18\x0c \x01(\t\x12\x15\n\rwifi_password\x18\r \x01(\t\x12\x14\n\x0cwifi_ap_mode\x18\x0e \x01(\x08\x12\x1b\n\x06region\x18\x0f \x01(\x0e\x32\x0b.RegionCode\x12&\n\x0e\x63harge_current\x18\x10 \x01(\x0e\x32\x0e.ChargeCurrent\x12\x11\n\tis_router\x18% \x01(\x08\x12\x14\n\x0cis_low_power\x18& \x01(\x08\x12\x16\n\x0e\x66ixed_position\x18\' \x01(\x08\x12\x17\n\x0fserial_disabled\x18( \x01(\x08\x12(\n\x0elocation_share\x18  \x01(\x0e\x32\x10.LocationSharing\x12$\n\rgps_operation\x18! \x01(\x0e\x32\r.GpsOperation\x12\x1b\n\x13gps_update_interval\x18\" \x01(\r\x12\x18\n\x10gps_attempt_time\x18$ \x01(\r\x12\x15\n\rgps_accept_2d\x18- \x01(\x08\x12\x13\n\x0bgps_max_dop\x18. \x01(\r\x12\x18\n\x10\x66requency_offset\x18) \x01(\x02\x12\x13\n\x0bmqtt_server\x18* \x01(\t\x12\x15\n\rmqtt_disabled\x18+ \x01(\x08\x12(\n\ngps_format\x18, \x01(\x0e\x32\x14.GpsCoordinateFormat\x12\x15\n\rfactory_reset\x18\x64 \x01(\x08\x12\x19\n\x11\x64\x65\x62ug_log_enabled\x18\x65 \x01(\x08\x12\x17\n\x0fignore_incoming\x18g \x03(\r\x12\x1c\n\x14serialplugin_enabled\x18x \x01(\x08\x12\x19\n\x11serialplugin_echo\x18y \x01(\x08\x12\x18\n\x10serialplugin_rxd\x18z \x01(\r\x12\x18\n\x10serialplugin_txd\x18{ \x01(\r\x12\x1c\n\x14serialplugin_timeout\x18| \x01(\r\x12\x19\n\x11serialplugin_mode\x18} \x01(\r\x12\'\n\x1f\x65xt_notification_plugin_enabled\x18~ \x01(\x08\x12)\n!ext_notification_plugin_output_ms\x18\x7f \x01(\r\x12\'\n\x1e\x65xt_notification_plugin_output\x18\x80\x01 \x01(\r\x12\'\n\x1e\x65xt_notification_plugin_active\x18\x81\x01 \x01(\x08\x12.\n%ext_notification_plugin_alert_message\x18\x82\x01 \x01(\x08\x12+\n\"ext_notification_plugin_alert_bell\x18\x83\x01 \x01(\x08\x12\"\n\x19range_test_plugin_enabled\x18\x84\x01 \x01(\x08\x12!\n\x18range_test_plugin_sender\x18\x85\x01 \x01(\r\x12\x1f\n\x16range_test_plugin_save\x18\x86\x01 \x01(\x08\x12%\n\x1cstore_forward_plugin_enabled\x18\x94\x01 \x01(\x08\x12\'\n\x1estore_forward_plugin_heartbeat\x18\x95\x01 \x01(\x08\x12%\n\x1cstore_forward_plugin_records\x18\x89\x01 \x01(\r\x12\x30\n\'store_forward_plugin_history_return_max\x18\x8a\x01 \x01(\r\x12\x33\n*store_forward_plugin_history_return_window\x18\x8b\x01 \x01(\r\x12=\n4environmental_measurement_plugin_measurement_enabled\x18\x8c\x01 \x01(\x08\x12\x38\n/environmental_measurement_plugin_screen_enabled\x18\x8d\x01 \x01(\x08\x12\x44\n;environmental_measurement_plugin_read_error_count_threshold\x18\x8e\x01 \x01(\r\x12\x39\n0environmental_measurement_plugin_update_interval\x18\x8f\x01 \x01(\r\x12;\n2environmental_measurement_plugin_recovery_interval\x18\x90\x01 \x01(\r\x12;\n2environmental_measurement_plugin_display_farenheit\x18\x91\x01 \x01(\x08\x12v\n,environmental_measurement_plugin_sensor_type\x18\x92\x01 \x01(\x0e\x32?.RadioConfig.UserPreferences.EnvironmentalMeasurementSensorType\x12\x34\n+environmental_measurement_plugin_sensor_pin\x18\x93\x01 \x01(\r\x12\x17\n\x0eposition_flags\x18\x96\x01 \x01(\r\x12\x1a\n\x11is_always_powered\x18\x97\x01 \x01(\x08\x12\"\n\x19\x61uto_screen_carousel_secs\x18\x98\x01 \x01(\r\x12\'\n\x1eon_battery_shutdown_after_secs\x18\x99\x01 \x01(\r\x12\x12\n\thop_limit\x18\x9a\x01 \x01(\r\x12\x16\n\rmqtt_username\x18\x9b\x01 \x01(\t\x12\x16\n\rmqtt_password\x18\x9c\x01 \x01(\t\"<\n\"EnvironmentalMeasurementSensorType\x12\t\n\x05\x44HT11\x10\x00\x12\x0b\n\x07\x44S18B20\x10\x01J\x06\x08\x88\x01\x10\x89\x01*f\n\nRegionCode\x12\t\n\x05Unset\x10\x00\x12\x06\n\x02US\x10\x01\x12\t\n\x05\x45U433\x10\x02\x12\t\n\x05\x45U865\x10\x03\x12\x06\n\x02\x43N\x10\x04\x12\x06\n\x02JP\x10\x05\x12\x07\n\x03\x41NZ\x10\x06\x12\x06\n\x02KR\x10\x07\x12\x06\n\x02TW\x10\x08\x12\x06\n\x02RU\x10\t*\xd1\x01\n\rChargeCurrent\x12\x0b\n\x07MAUnset\x10\x00\x12\t\n\x05MA100\x10\x01\x12\t\n\x05MA190\x10\x02\x12\t\n\x05MA280\x10\x03\x12\t\n\x05MA360\x10\x04\x12\t\n\x05MA450\x10\x05\x12\t\n\x05MA550\x10\x06\x12\t\n\x05MA630\x10\x07\x12\t\n\x05MA700\x10\x08\x12\t\n\x05MA780\x10\t\x12\t\n\x05MA880\x10\n\x12\t\n\x05MA960\x10\x0b\x12\n\n\x06MA1000\x10\x0c\x12\n\n\x06MA1080\x10\r\x12\n\n\x06MA1160\x10\x0e\x12\n\n\x06MA1240\x10\x0f\x12\n\n\x06MA1320\x10\x10*j\n\x0cGpsOperation\x12\x0e\n\nGpsOpUnset\x10\x00\x12\x13\n\x0fGpsOpStationary\x10\x01\x12\x0f\n\x0bGpsOpMobile\x10\x02\x12\x11\n\rGpsOpTimeOnly\x10\x03\x12\x11\n\rGpsOpDisabled\x10\x04*\x83\x01\n\x13GpsCoordinateFormat\x12\x10\n\x0cGpsFormatDec\x10\x00\x12\x10\n\x0cGpsFormatDMS\x10\x01\x12\x10\n\x0cGpsFormatUTM\x10\x02\x12\x11\n\rGpsFormatMGRS\x10\x03\x12\x10\n\x0cGpsFormatOLC\x10\x04\x12\x11\n\rGpsFormatOSGR\x10\x05*@\n\x0fLocationSharing\x12\x0c\n\x08LocUnset\x10\x00\x12\x0e\n\nLocEnabled\x10\x01\x12\x0f\n\x0bLocDisabled\x10\x02*\xbc\x01\n\rPositionFlags\x12\x11\n\rPOS_UNDEFINED\x10\x00\x12\x10\n\x0cPOS_ALTITUDE\x10\x01\x12\x0f\n\x0bPOS_ALT_MSL\x10\x02\x12\x0f\n\x0bPOS_GEO_SEP\x10\x04\x12\x0b\n\x07POS_DOP\x10\x08\x12\r\n\tPOS_HVDOP\x10\x10\x12\x0f\n\x0bPOS_BATTERY\x10 \x12\x11\n\rPOS_SATINVIEW\x10@\x12\x10\n\x0bPOS_SEQ_NOS\x10\x80\x01\x12\x12\n\rPOS_TIMESTAMP\x10\x80\x02\x42M\n\x13\x63om.geeksville.meshB\x11RadioConfigProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-)
-
-_REGIONCODE = _descriptor.EnumDescriptor(
-  name='RegionCode',
-  full_name='RegionCode',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='Unset', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='US', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='EU433', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='EU865', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='CN', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='JP', index=5, number=5,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ANZ', index=6, number=6,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='KR', index=7, number=7,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='TW', index=8, number=8,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='RU', index=9, number=9,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=2559,
-  serialized_end=2661,
-)
-_sym_db.RegisterEnumDescriptor(_REGIONCODE)
-
-RegionCode = enum_type_wrapper.EnumTypeWrapper(_REGIONCODE)
-_CHARGECURRENT = _descriptor.EnumDescriptor(
-  name='ChargeCurrent',
-  full_name='ChargeCurrent',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='MAUnset', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA100', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA190', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA280', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA360', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA450', index=5, number=5,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA550', index=6, number=6,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA630', index=7, number=7,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA700', index=8, number=8,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA780', index=9, number=9,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA880', index=10, number=10,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA960', index=11, number=11,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA1000', index=12, number=12,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA1080', index=13, number=13,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA1160', index=14, number=14,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA1240', index=15, number=15,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='MA1320', index=16, number=16,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=2664,
-  serialized_end=2873,
-)
-_sym_db.RegisterEnumDescriptor(_CHARGECURRENT)
-
-ChargeCurrent = enum_type_wrapper.EnumTypeWrapper(_CHARGECURRENT)
-_GPSOPERATION = _descriptor.EnumDescriptor(
-  name='GpsOperation',
-  full_name='GpsOperation',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='GpsOpUnset', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GpsOpStationary', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GpsOpMobile', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GpsOpTimeOnly', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GpsOpDisabled', index=4, number=4,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=2875,
-  serialized_end=2981,
-)
-_sym_db.RegisterEnumDescriptor(_GPSOPERATION)
-
-GpsOperation = enum_type_wrapper.EnumTypeWrapper(_GPSOPERATION)
-_GPSCOORDINATEFORMAT = _descriptor.EnumDescriptor(
-  name='GpsCoordinateFormat',
-  full_name='GpsCoordinateFormat',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='GpsFormatDec', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GpsFormatDMS', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GpsFormatUTM', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GpsFormatMGRS', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GpsFormatOLC', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GpsFormatOSGR', index=5, number=5,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=2984,
-  serialized_end=3115,
-)
-_sym_db.RegisterEnumDescriptor(_GPSCOORDINATEFORMAT)
-
-GpsCoordinateFormat = enum_type_wrapper.EnumTypeWrapper(_GPSCOORDINATEFORMAT)
-_LOCATIONSHARING = _descriptor.EnumDescriptor(
-  name='LocationSharing',
-  full_name='LocationSharing',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='LocUnset', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='LocEnabled', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='LocDisabled', index=2, number=2,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=3117,
-  serialized_end=3181,
-)
-_sym_db.RegisterEnumDescriptor(_LOCATIONSHARING)
-
-LocationSharing = enum_type_wrapper.EnumTypeWrapper(_LOCATIONSHARING)
-_POSITIONFLAGS = _descriptor.EnumDescriptor(
-  name='PositionFlags',
-  full_name='PositionFlags',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='POS_UNDEFINED', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POS_ALTITUDE', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POS_ALT_MSL', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POS_GEO_SEP', index=3, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POS_DOP', index=4, number=8,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POS_HVDOP', index=5, number=16,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POS_BATTERY', index=6, number=32,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POS_SATINVIEW', index=7, number=64,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POS_SEQ_NOS', index=8, number=128,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='POS_TIMESTAMP', index=9, number=256,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=3184,
-  serialized_end=3372,
-)
-_sym_db.RegisterEnumDescriptor(_POSITIONFLAGS)
-
-PositionFlags = enum_type_wrapper.EnumTypeWrapper(_POSITIONFLAGS)
-Unset = 0
-US = 1
-EU433 = 2
-EU865 = 3
-CN = 4
-JP = 5
-ANZ = 6
-KR = 7
-TW = 8
-RU = 9
-MAUnset = 0
-MA100 = 1
-MA190 = 2
-MA280 = 3
-MA360 = 4
-MA450 = 5
-MA550 = 6
-MA630 = 7
-MA700 = 8
-MA780 = 9
-MA880 = 10
-MA960 = 11
-MA1000 = 12
-MA1080 = 13
-MA1160 = 14
-MA1240 = 15
-MA1320 = 16
-GpsOpUnset = 0
-GpsOpStationary = 1
-GpsOpMobile = 2
-GpsOpTimeOnly = 3
-GpsOpDisabled = 4
-GpsFormatDec = 0
-GpsFormatDMS = 1
-GpsFormatUTM = 2
-GpsFormatMGRS = 3
-GpsFormatOLC = 4
-GpsFormatOSGR = 5
-LocUnset = 0
-LocEnabled = 1
-LocDisabled = 2
-POS_UNDEFINED = 0
-POS_ALTITUDE = 1
-POS_ALT_MSL = 2
-POS_GEO_SEP = 4
-POS_DOP = 8
-POS_HVDOP = 16
-POS_BATTERY = 32
-POS_SATINVIEW = 64
-POS_SEQ_NOS = 128
-POS_TIMESTAMP = 256
-
-
-_RADIOCONFIG_USERPREFERENCES_ENVIRONMENTALMEASUREMENTSENSORTYPE = _descriptor.EnumDescriptor(
-  name='EnvironmentalMeasurementSensorType',
-  full_name='RadioConfig.UserPreferences.EnvironmentalMeasurementSensorType',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='DHT11', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='DS18B20', index=1, number=1,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=2489,
-  serialized_end=2549,
-)
-_sym_db.RegisterEnumDescriptor(_RADIOCONFIG_USERPREFERENCES_ENVIRONMENTALMEASUREMENTSENSORTYPE)
-
-
-_RADIOCONFIG_USERPREFERENCES = _descriptor.Descriptor(
-  name='UserPreferences',
-  full_name='RadioConfig.UserPreferences',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='position_broadcast_secs', full_name='RadioConfig.UserPreferences.position_broadcast_secs', index=0,
-      number=1, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='position_broadcast_smart', full_name='RadioConfig.UserPreferences.position_broadcast_smart', index=1,
-      number=17, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='send_owner_interval', full_name='RadioConfig.UserPreferences.send_owner_interval', index=2,
-      number=2, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='wait_bluetooth_secs', full_name='RadioConfig.UserPreferences.wait_bluetooth_secs', index=3,
-      number=4, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='screen_on_secs', full_name='RadioConfig.UserPreferences.screen_on_secs', index=4,
-      number=5, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='phone_timeout_secs', full_name='RadioConfig.UserPreferences.phone_timeout_secs', index=5,
-      number=6, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='phone_sds_timeout_sec', full_name='RadioConfig.UserPreferences.phone_sds_timeout_sec', index=6,
-      number=7, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='mesh_sds_timeout_secs', full_name='RadioConfig.UserPreferences.mesh_sds_timeout_secs', index=7,
-      number=8, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='sds_secs', full_name='RadioConfig.UserPreferences.sds_secs', index=8,
-      number=9, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ls_secs', full_name='RadioConfig.UserPreferences.ls_secs', index=9,
-      number=10, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='min_wake_secs', full_name='RadioConfig.UserPreferences.min_wake_secs', index=10,
-      number=11, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='wifi_ssid', full_name='RadioConfig.UserPreferences.wifi_ssid', index=11,
-      number=12, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='wifi_password', full_name='RadioConfig.UserPreferences.wifi_password', index=12,
-      number=13, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='wifi_ap_mode', full_name='RadioConfig.UserPreferences.wifi_ap_mode', index=13,
-      number=14, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='region', full_name='RadioConfig.UserPreferences.region', index=14,
-      number=15, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='charge_current', full_name='RadioConfig.UserPreferences.charge_current', index=15,
-      number=16, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='is_router', full_name='RadioConfig.UserPreferences.is_router', index=16,
-      number=37, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='is_low_power', full_name='RadioConfig.UserPreferences.is_low_power', index=17,
-      number=38, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='fixed_position', full_name='RadioConfig.UserPreferences.fixed_position', index=18,
-      number=39, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='serial_disabled', full_name='RadioConfig.UserPreferences.serial_disabled', index=19,
-      number=40, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='location_share', full_name='RadioConfig.UserPreferences.location_share', index=20,
-      number=32, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gps_operation', full_name='RadioConfig.UserPreferences.gps_operation', index=21,
-      number=33, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gps_update_interval', full_name='RadioConfig.UserPreferences.gps_update_interval', index=22,
-      number=34, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gps_attempt_time', full_name='RadioConfig.UserPreferences.gps_attempt_time', index=23,
-      number=36, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gps_accept_2d', full_name='RadioConfig.UserPreferences.gps_accept_2d', index=24,
-      number=45, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gps_max_dop', full_name='RadioConfig.UserPreferences.gps_max_dop', index=25,
-      number=46, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='frequency_offset', full_name='RadioConfig.UserPreferences.frequency_offset', index=26,
-      number=41, type=2, cpp_type=6, label=1,
-      has_default_value=False, default_value=float(0),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='mqtt_server', full_name='RadioConfig.UserPreferences.mqtt_server', index=27,
-      number=42, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='mqtt_disabled', full_name='RadioConfig.UserPreferences.mqtt_disabled', index=28,
-      number=43, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gps_format', full_name='RadioConfig.UserPreferences.gps_format', index=29,
-      number=44, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='factory_reset', full_name='RadioConfig.UserPreferences.factory_reset', index=30,
-      number=100, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='debug_log_enabled', full_name='RadioConfig.UserPreferences.debug_log_enabled', index=31,
-      number=101, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ignore_incoming', full_name='RadioConfig.UserPreferences.ignore_incoming', index=32,
-      number=103, type=13, cpp_type=3, label=3,
-      has_default_value=False, default_value=[],
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='serialplugin_enabled', full_name='RadioConfig.UserPreferences.serialplugin_enabled', index=33,
-      number=120, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='serialplugin_echo', full_name='RadioConfig.UserPreferences.serialplugin_echo', index=34,
-      number=121, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='serialplugin_rxd', full_name='RadioConfig.UserPreferences.serialplugin_rxd', index=35,
-      number=122, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='serialplugin_txd', full_name='RadioConfig.UserPreferences.serialplugin_txd', index=36,
-      number=123, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='serialplugin_timeout', full_name='RadioConfig.UserPreferences.serialplugin_timeout', index=37,
-      number=124, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='serialplugin_mode', full_name='RadioConfig.UserPreferences.serialplugin_mode', index=38,
-      number=125, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ext_notification_plugin_enabled', full_name='RadioConfig.UserPreferences.ext_notification_plugin_enabled', index=39,
-      number=126, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ext_notification_plugin_output_ms', full_name='RadioConfig.UserPreferences.ext_notification_plugin_output_ms', index=40,
-      number=127, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ext_notification_plugin_output', full_name='RadioConfig.UserPreferences.ext_notification_plugin_output', index=41,
-      number=128, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ext_notification_plugin_active', full_name='RadioConfig.UserPreferences.ext_notification_plugin_active', index=42,
-      number=129, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ext_notification_plugin_alert_message', full_name='RadioConfig.UserPreferences.ext_notification_plugin_alert_message', index=43,
-      number=130, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='ext_notification_plugin_alert_bell', full_name='RadioConfig.UserPreferences.ext_notification_plugin_alert_bell', index=44,
-      number=131, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='range_test_plugin_enabled', full_name='RadioConfig.UserPreferences.range_test_plugin_enabled', index=45,
-      number=132, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='range_test_plugin_sender', full_name='RadioConfig.UserPreferences.range_test_plugin_sender', index=46,
-      number=133, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='range_test_plugin_save', full_name='RadioConfig.UserPreferences.range_test_plugin_save', index=47,
-      number=134, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='store_forward_plugin_enabled', full_name='RadioConfig.UserPreferences.store_forward_plugin_enabled', index=48,
-      number=148, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='store_forward_plugin_heartbeat', full_name='RadioConfig.UserPreferences.store_forward_plugin_heartbeat', index=49,
-      number=149, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='store_forward_plugin_records', full_name='RadioConfig.UserPreferences.store_forward_plugin_records', index=50,
-      number=137, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='store_forward_plugin_history_return_max', full_name='RadioConfig.UserPreferences.store_forward_plugin_history_return_max', index=51,
-      number=138, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='store_forward_plugin_history_return_window', full_name='RadioConfig.UserPreferences.store_forward_plugin_history_return_window', index=52,
-      number=139, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='environmental_measurement_plugin_measurement_enabled', full_name='RadioConfig.UserPreferences.environmental_measurement_plugin_measurement_enabled', index=53,
-      number=140, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='environmental_measurement_plugin_screen_enabled', full_name='RadioConfig.UserPreferences.environmental_measurement_plugin_screen_enabled', index=54,
-      number=141, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='environmental_measurement_plugin_read_error_count_threshold', full_name='RadioConfig.UserPreferences.environmental_measurement_plugin_read_error_count_threshold', index=55,
-      number=142, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='environmental_measurement_plugin_update_interval', full_name='RadioConfig.UserPreferences.environmental_measurement_plugin_update_interval', index=56,
-      number=143, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='environmental_measurement_plugin_recovery_interval', full_name='RadioConfig.UserPreferences.environmental_measurement_plugin_recovery_interval', index=57,
-      number=144, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='environmental_measurement_plugin_display_farenheit', full_name='RadioConfig.UserPreferences.environmental_measurement_plugin_display_farenheit', index=58,
-      number=145, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='environmental_measurement_plugin_sensor_type', full_name='RadioConfig.UserPreferences.environmental_measurement_plugin_sensor_type', index=59,
-      number=146, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='environmental_measurement_plugin_sensor_pin', full_name='RadioConfig.UserPreferences.environmental_measurement_plugin_sensor_pin', index=60,
-      number=147, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='position_flags', full_name='RadioConfig.UserPreferences.position_flags', index=61,
-      number=150, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='is_always_powered', full_name='RadioConfig.UserPreferences.is_always_powered', index=62,
-      number=151, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='auto_screen_carousel_secs', full_name='RadioConfig.UserPreferences.auto_screen_carousel_secs', index=63,
-      number=152, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='on_battery_shutdown_after_secs', full_name='RadioConfig.UserPreferences.on_battery_shutdown_after_secs', index=64,
-      number=153, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='hop_limit', full_name='RadioConfig.UserPreferences.hop_limit', index=65,
-      number=154, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='mqtt_username', full_name='RadioConfig.UserPreferences.mqtt_username', index=66,
-      number=155, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='mqtt_password', full_name='RadioConfig.UserPreferences.mqtt_password', index=67,
-      number=156, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-    _RADIOCONFIG_USERPREFERENCES_ENVIRONMENTALMEASUREMENTSENSORTYPE,
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=89,
-  serialized_end=2557,
-)
-
-_RADIOCONFIG = _descriptor.Descriptor(
-  name='RadioConfig',
-  full_name='RadioConfig',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='preferences', full_name='RadioConfig.preferences', index=0,
-      number=1, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[_RADIOCONFIG_USERPREFERENCES, ],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=22,
-  serialized_end=2557,
-)
-
-_RADIOCONFIG_USERPREFERENCES.fields_by_name['region'].enum_type = _REGIONCODE
-_RADIOCONFIG_USERPREFERENCES.fields_by_name['charge_current'].enum_type = _CHARGECURRENT
-_RADIOCONFIG_USERPREFERENCES.fields_by_name['location_share'].enum_type = _LOCATIONSHARING
-_RADIOCONFIG_USERPREFERENCES.fields_by_name['gps_operation'].enum_type = _GPSOPERATION
-_RADIOCONFIG_USERPREFERENCES.fields_by_name['gps_format'].enum_type = _GPSCOORDINATEFORMAT
-_RADIOCONFIG_USERPREFERENCES.fields_by_name['environmental_measurement_plugin_sensor_type'].enum_type = _RADIOCONFIG_USERPREFERENCES_ENVIRONMENTALMEASUREMENTSENSORTYPE
-_RADIOCONFIG_USERPREFERENCES.containing_type = _RADIOCONFIG
-_RADIOCONFIG_USERPREFERENCES_ENVIRONMENTALMEASUREMENTSENSORTYPE.containing_type = _RADIOCONFIG_USERPREFERENCES
-_RADIOCONFIG.fields_by_name['preferences'].message_type = _RADIOCONFIG_USERPREFERENCES
-DESCRIPTOR.message_types_by_name['RadioConfig'] = _RADIOCONFIG
-DESCRIPTOR.enum_types_by_name['RegionCode'] = _REGIONCODE
-DESCRIPTOR.enum_types_by_name['ChargeCurrent'] = _CHARGECURRENT
-DESCRIPTOR.enum_types_by_name['GpsOperation'] = _GPSOPERATION
-DESCRIPTOR.enum_types_by_name['GpsCoordinateFormat'] = _GPSCOORDINATEFORMAT
-DESCRIPTOR.enum_types_by_name['LocationSharing'] = _LOCATIONSHARING
-DESCRIPTOR.enum_types_by_name['PositionFlags'] = _POSITIONFLAGS
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-RadioConfig = _reflection.GeneratedProtocolMessageType('RadioConfig', (_message.Message,), {
-
-  'UserPreferences' : _reflection.GeneratedProtocolMessageType('UserPreferences', (_message.Message,), {
-    'DESCRIPTOR' : _RADIOCONFIG_USERPREFERENCES,
-    '__module__' : 'radioconfig_pb2'
-    # @@protoc_insertion_point(class_scope:RadioConfig.UserPreferences)
-    })
-  ,
-  'DESCRIPTOR' : _RADIOCONFIG,
-  '__module__' : 'radioconfig_pb2'
-  # @@protoc_insertion_point(class_scope:RadioConfig)
-  })
-_sym_db.RegisterMessage(RadioConfig)
-_sym_db.RegisterMessage(RadioConfig.UserPreferences)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class RadioConfig -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var PREFERENCES_FIELD_NUMBER
-
-
-
-
var UserPreferences
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var preferences
-
-

Getter for preferences.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/remote_hardware.html b/docs/meshtastic/remote_hardware.html deleted file mode 100644 index 145872c..0000000 --- a/docs/meshtastic/remote_hardware.html +++ /dev/null @@ -1,324 +0,0 @@ - - - - - - -meshtastic.remote_hardware API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.remote_hardware

-
-
-

Remote hardware

-
- -Expand source code - -
"""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
-    """
-    logging.debug(f"packet:{packet} interface:{interface}")
-    hw = packet["decoded"]["remotehw"]
-    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:
-    """
-    This is the client code to control/monitor simple hardware built into the
-    meshtastic devices.  It is intended to be both a useful API/service and example
-    code for how you can connect to your own custom meshtastic services
-    """
-
-    def __init__(self, iface):
-        """
-        Constructor
-
-        iface is the already open MeshInterface instance
-        """
-        self.iface = iface
-        ch = iface.localNode.getChannelByName("gpio")
-        if not ch:
-            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")
-
-    def _sendHardware(self, nodeid, r, wantResponse=False, onResponse=None):
-        if not nodeid:
-            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)
-
-    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
-        r.gpio_value = vals
-        return self._sendHardware(nodeid, r)
-
-    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
-        return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse)
-
-    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)
-
-
-
-
-
-
-
-

Functions

-
-
-def onGPIOreceive(packet, interface) -
-
-

Callback for received GPIO responses

-
- -Expand source code - -
def onGPIOreceive(packet, interface):
-    """Callback for received GPIO responses
-    """
-    logging.debug(f"packet:{packet} interface:{interface}")
-    hw = packet["decoded"]["remotehw"]
-    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
-
-
-
-
-
-

Classes

-
-
-class RemoteHardwareClient -(iface) -
-
-

This is the client code to control/monitor simple hardware built into the -meshtastic devices. -It is intended to be both a useful API/service and example -code for how you can connect to your own custom meshtastic services

-

Constructor

-

iface is the already open MeshInterface instance

-
- -Expand source code - -
class RemoteHardwareClient:
-    """
-    This is the client code to control/monitor simple hardware built into the
-    meshtastic devices.  It is intended to be both a useful API/service and example
-    code for how you can connect to your own custom meshtastic services
-    """
-
-    def __init__(self, iface):
-        """
-        Constructor
-
-        iface is the already open MeshInterface instance
-        """
-        self.iface = iface
-        ch = iface.localNode.getChannelByName("gpio")
-        if not ch:
-            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")
-
-    def _sendHardware(self, nodeid, r, wantResponse=False, onResponse=None):
-        if not nodeid:
-            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)
-
-    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
-        r.gpio_value = vals
-        return self._sendHardware(nodeid, r)
-
-    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
-        return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse)
-
-    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)
-
-

Methods

-
-
-def readGPIOs(self, nodeid, mask, onResponse=None) -
-
-

Read the specified bits from GPIO inputs on the device

-
- -Expand source code - -
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
-    return self._sendHardware(nodeid, r, wantResponse=True, onResponse=onResponse)
-
-
-
-def watchGPIOs(self, nodeid, mask) -
-
-

Watch the specified bits from GPIO inputs on the device for changes

-
- -Expand source code - -
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)
-
-
-
-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

-
- -Expand source code - -
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
-    r.gpio_value = vals
-    return self._sendHardware(nodeid, r)
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/remote_hardware_pb2.html b/docs/meshtastic/remote_hardware_pb2.html deleted file mode 100644 index ff58876..0000000 --- a/docs/meshtastic/remote_hardware_pb2.html +++ /dev/null @@ -1,822 +0,0 @@ - - - - - - -meshtastic.remote_hardware_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.remote_hardware_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: remote_hardware.proto
-
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='remote_hardware.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\016RemoteHardwareH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\x15remote_hardware.proto\"\xca\x01\n\x0fHardwareMessage\x12\"\n\x03typ\x18\x01 \x01(\x0e\x32\x15.HardwareMessage.Type\x12\x11\n\tgpio_mask\x18\x02 \x01(\x04\x12\x12\n\ngpio_value\x18\x03 \x01(\x04\"l\n\x04Type\x12\t\n\x05UNSET\x10\x00\x12\x0f\n\x0bWRITE_GPIOS\x10\x01\x12\x0f\n\x0bWATCH_GPIOS\x10\x02\x12\x11\n\rGPIOS_CHANGED\x10\x03\x12\x0e\n\nREAD_GPIOS\x10\x04\x12\x14\n\x10READ_GPIOS_REPLY\x10\x05\x42J\n\x13\x63om.geeksville.meshB\x0eRemoteHardwareH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-)
-
-
-
-_HARDWAREMESSAGE_TYPE = _descriptor.EnumDescriptor(
-  name='Type',
-  full_name='HardwareMessage.Type',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='UNSET', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='WRITE_GPIOS', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='WATCH_GPIOS', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='GPIOS_CHANGED', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='READ_GPIOS', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='READ_GPIOS_REPLY', index=5, number=5,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=120,
-  serialized_end=228,
-)
-_sym_db.RegisterEnumDescriptor(_HARDWAREMESSAGE_TYPE)
-
-
-_HARDWAREMESSAGE = _descriptor.Descriptor(
-  name='HardwareMessage',
-  full_name='HardwareMessage',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='typ', full_name='HardwareMessage.typ', index=0,
-      number=1, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gpio_mask', full_name='HardwareMessage.gpio_mask', index=1,
-      number=2, type=4, cpp_type=4, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='gpio_value', full_name='HardwareMessage.gpio_value', index=2,
-      number=3, type=4, cpp_type=4, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-    _HARDWAREMESSAGE_TYPE,
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=26,
-  serialized_end=228,
-)
-
-_HARDWAREMESSAGE.fields_by_name['typ'].enum_type = _HARDWAREMESSAGE_TYPE
-_HARDWAREMESSAGE_TYPE.containing_type = _HARDWAREMESSAGE
-DESCRIPTOR.message_types_by_name['HardwareMessage'] = _HARDWAREMESSAGE
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-HardwareMessage = _reflection.GeneratedProtocolMessageType('HardwareMessage', (_message.Message,), {
-  'DESCRIPTOR' : _HARDWAREMESSAGE,
-  '__module__' : 'remote_hardware_pb2'
-  # @@protoc_insertion_point(class_scope:HardwareMessage)
-  })
-_sym_db.RegisterMessage(HardwareMessage)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class HardwareMessage -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var GPIOS_CHANGED
-
-
-
-
var GPIO_MASK_FIELD_NUMBER
-
-
-
-
var GPIO_VALUE_FIELD_NUMBER
-
-
-
-
var READ_GPIOS
-
-
-
-
var READ_GPIOS_REPLY
-
-
-
-
var TYP_FIELD_NUMBER
-
-
-
-
var Type
-
-
-
-
var UNSET
-
-
-
-
var WATCH_GPIOS
-
-
-
-
var WRITE_GPIOS
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var gpio_mask
-
-

Getter for gpio_mask.

-
- -Expand source code - -
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)
-
-
-
var gpio_value
-
-

Getter for gpio_value.

-
- -Expand source code - -
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)
-
-
-
var typ
-
-

Getter for typ.

-
- -Expand source code - -
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)
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/serial_interface.html b/docs/meshtastic/serial_interface.html deleted file mode 100644 index 8f7ef3e..0000000 --- a/docs/meshtastic/serial_interface.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - -meshtastic.serial_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.serial_interface

-
-
-

Serial interface class

-
- -Expand source code - -
""" Serial interface class
-"""
-import logging
-import platform
-import os
-import stat
-import serial
-
-import meshtastic.util
-from .stream_interface import StreamInterface
-
-class SerialInterface(StreamInterface):
-    """Interface class for meshtastic devices over a serial link"""
-
-    def __init__(self, devPath=None, debugOut=None, noProto=False, connectNow=True):
-        """Constructor, opens a connection to a specified serial port, or if unspecified try to
-        find one Meshtastic device by probing
-
-        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})
-        """
-
-        if devPath is None:
-            ports = meshtastic.util.findPorts()
-            logging.debug(f"ports:{ports}")
-            if len(ports) == 0:
-                meshtastic.util.our_exit("Warning: No Meshtastic devices detected.")
-            elif len(ports) > 1:
-                message = "Warning: Multiple serial ports were detected so one serial port must be specified with the '--port'.\n"
-                message += f"  Ports detected:{ports}"
-                meshtastic.util.our_exit(message)
-            else:
-                devPath = ports[0]
-
-        logging.debug(f"Connecting to {devPath}")
-
-        # Note: we provide None for port here, because we will be opening it later
-        self.stream = serial.Serial(
-            None, 921600, exclusive=True, timeout=0.5, write_timeout=0)
-
-        # rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset
-        self.stream.port = devPath
-
-        # HACK: If the platform driving the serial port is unable to leave the RTS pin in high-impedance
-        # mode, set RTS to false so that the device platform won't be reset spuriously.
-        # Linux does this properly, so don't apply this hack on Linux (because it makes the reset button not work).
-        if self._hostPlatformAlwaysDrivesUartRts():
-            self.stream.rts = False
-        self.stream.open()
-
-        StreamInterface.__init__(
-            self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
-
-    """true if platform driving the serial port is Windows Subsystem for Linux 1."""
-    def _isWsl1(self):
-        # WSL1 identifies itself as Linux, but has a special char device at /dev/lxss for use with session control,
-        # e.g. /init.  We should treat WSL1 as Windows for the RTS-driving hack because the underlying platfrom
-        # serial driver for the CP21xx still exhibits the buggy behavior.
-        # WSL2 is not covered here, as it does not (as of 2021-May-25) support the appropriate functionality to
-        # share or pass-through serial ports.
-        try:
-            # Claims to be Linux, but has /dev/lxss; must be WSL 1
-            return platform.system() == 'Linux' and stat.S_ISCHR(os.stat('/dev/lxss').st_mode)
-        except:
-            # Couldn't stat /dev/lxss special device; not WSL1
-            return False
-
-    def _hostPlatformAlwaysDrivesUartRts(self):
-        # OS-X/Windows seems to have a bug in its CP21xx serial drivers.  It ignores that we asked for no RTSCTS
-        # control and will always drive RTS either high or low (rather than letting the CP102 leave
-        # it as an open-collector floating pin).
-        # TODO: When WSL2 supports USB passthrough, this will get messier.  If/when WSL2 gets virtual serial
-        # ports that "share" the Windows serial port (and thus the Windows drivers), this code will need to be
-        # updated to reflect that as well -- or if T-Beams get made with an alternate USB to UART bridge that has
-        # a less buggy driver.
-        return platform.system() != 'Linux' or self._isWsl1()
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SerialInterface -(devPath=None, debugOut=None, noProto=False, connectNow=True) -
-
-

Interface class for meshtastic devices over a serial link

-

Constructor, opens a connection to a specified serial port, or if unspecified try to -find one Meshtastic device by probing

-

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})

-
- -Expand source code - -
class SerialInterface(StreamInterface):
-    """Interface class for meshtastic devices over a serial link"""
-
-    def __init__(self, devPath=None, debugOut=None, noProto=False, connectNow=True):
-        """Constructor, opens a connection to a specified serial port, or if unspecified try to
-        find one Meshtastic device by probing
-
-        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})
-        """
-
-        if devPath is None:
-            ports = meshtastic.util.findPorts()
-            logging.debug(f"ports:{ports}")
-            if len(ports) == 0:
-                meshtastic.util.our_exit("Warning: No Meshtastic devices detected.")
-            elif len(ports) > 1:
-                message = "Warning: Multiple serial ports were detected so one serial port must be specified with the '--port'.\n"
-                message += f"  Ports detected:{ports}"
-                meshtastic.util.our_exit(message)
-            else:
-                devPath = ports[0]
-
-        logging.debug(f"Connecting to {devPath}")
-
-        # Note: we provide None for port here, because we will be opening it later
-        self.stream = serial.Serial(
-            None, 921600, exclusive=True, timeout=0.5, write_timeout=0)
-
-        # rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset
-        self.stream.port = devPath
-
-        # HACK: If the platform driving the serial port is unable to leave the RTS pin in high-impedance
-        # mode, set RTS to false so that the device platform won't be reset spuriously.
-        # Linux does this properly, so don't apply this hack on Linux (because it makes the reset button not work).
-        if self._hostPlatformAlwaysDrivesUartRts():
-            self.stream.rts = False
-        self.stream.open()
-
-        StreamInterface.__init__(
-            self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
-
-    """true if platform driving the serial port is Windows Subsystem for Linux 1."""
-    def _isWsl1(self):
-        # WSL1 identifies itself as Linux, but has a special char device at /dev/lxss for use with session control,
-        # e.g. /init.  We should treat WSL1 as Windows for the RTS-driving hack because the underlying platfrom
-        # serial driver for the CP21xx still exhibits the buggy behavior.
-        # WSL2 is not covered here, as it does not (as of 2021-May-25) support the appropriate functionality to
-        # share or pass-through serial ports.
-        try:
-            # Claims to be Linux, but has /dev/lxss; must be WSL 1
-            return platform.system() == 'Linux' and stat.S_ISCHR(os.stat('/dev/lxss').st_mode)
-        except:
-            # Couldn't stat /dev/lxss special device; not WSL1
-            return False
-
-    def _hostPlatformAlwaysDrivesUartRts(self):
-        # OS-X/Windows seems to have a bug in its CP21xx serial drivers.  It ignores that we asked for no RTSCTS
-        # control and will always drive RTS either high or low (rather than letting the CP102 leave
-        # it as an open-collector floating pin).
-        # TODO: When WSL2 supports USB passthrough, this will get messier.  If/when WSL2 gets virtual serial
-        # ports that "share" the Windows serial port (and thus the Windows drivers), this code will need to be
-        # updated to reflect that as well -- or if T-Beams get made with an alternate USB to UART bridge that has
-        # a less buggy driver.
-        return platform.system() != 'Linux' or self._isWsl1()
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/storeforward_pb2.html b/docs/meshtastic/storeforward_pb2.html deleted file mode 100644 index c053c6d..0000000 --- a/docs/meshtastic/storeforward_pb2.html +++ /dev/null @@ -1,1165 +0,0 @@ - - - - - - -meshtastic.storeforward_pb2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.storeforward_pb2

-
-
-
- -Expand source code - -
# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: storeforward.proto
-
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
-  name='storeforward.proto',
-  package='',
-  syntax='proto3',
-  serialized_options=b'\n\023com.geeksville.meshB\025StoreAndForwardProtosH\003Z!github.com/meshtastic/gomeshproto',
-  serialized_pb=b'\n\x12storeforward.proto\"\x8a\x06\n\x0fStoreAndForward\x12,\n\x02rr\x18\x01 \x01(\x0e\x32 .StoreAndForward.RequestResponse\x12*\n\x05stats\x18\x02 \x01(\x0b\x32\x1b.StoreAndForward.Statistics\x12)\n\x07history\x18\x03 \x01(\x0b\x32\x18.StoreAndForward.History\x12-\n\theartbeat\x18\x04 \x01(\x0b\x32\x1a.StoreAndForward.Heartbeat\x1a\xcd\x01\n\nStatistics\x12\x16\n\x0emessages_total\x18\x01 \x01(\r\x12\x16\n\x0emessages_saved\x18\x02 \x01(\r\x12\x14\n\x0cmessages_max\x18\x03 \x01(\r\x12\x0f\n\x07up_time\x18\x04 \x01(\r\x12\x10\n\x08requests\x18\x05 \x01(\r\x12\x18\n\x10requests_history\x18\x06 \x01(\r\x12\x11\n\theartbeat\x18\x07 \x01(\x08\x12\x12\n\nreturn_max\x18\x08 \x01(\r\x12\x15\n\rreturn_window\x18\t \x01(\r\x1aI\n\x07History\x12\x18\n\x10history_messages\x18\x01 \x01(\r\x12\x0e\n\x06window\x18\x02 \x01(\r\x12\x14\n\x0clast_request\x18\x03 \x01(\r\x1a.\n\tHeartbeat\x12\x0e\n\x06period\x18\x01 \x01(\r\x12\x11\n\tsecondary\x18\x02 \x01(\r\"\xf7\x01\n\x0fRequestResponse\x12\t\n\x05UNSET\x10\x00\x12\x10\n\x0cROUTER_ERROR\x10\x01\x12\x14\n\x10ROUTER_HEARTBEAT\x10\x02\x12\x0f\n\x0bROUTER_PING\x10\x03\x12\x0f\n\x0bROUTER_PONG\x10\x04\x12\x0f\n\x0bROUTER_BUSY\x10\x05\x12\x12\n\x0eROUTER_HISTORY\x10\x06\x12\x10\n\x0c\x43LIENT_ERROR\x10\x65\x12\x12\n\x0e\x43LIENT_HISTORY\x10\x66\x12\x10\n\x0c\x43LIENT_STATS\x10g\x12\x0f\n\x0b\x43LIENT_PING\x10h\x12\x0f\n\x0b\x43LIENT_PONG\x10i\x12\x10\n\x0c\x43LIENT_ABORT\x10jBQ\n\x13\x63om.geeksville.meshB\x15StoreAndForwardProtosH\x03Z!github.com/meshtastic/gomeshprotob\x06proto3'
-)
-
-
-
-_STOREANDFORWARD_REQUESTRESPONSE = _descriptor.EnumDescriptor(
-  name='RequestResponse',
-  full_name='StoreAndForward.RequestResponse',
-  filename=None,
-  file=DESCRIPTOR,
-  values=[
-    _descriptor.EnumValueDescriptor(
-      name='UNSET', index=0, number=0,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ROUTER_ERROR', index=1, number=1,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ROUTER_HEARTBEAT', index=2, number=2,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ROUTER_PING', index=3, number=3,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ROUTER_PONG', index=4, number=4,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ROUTER_BUSY', index=5, number=5,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='ROUTER_HISTORY', index=6, number=6,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='CLIENT_ERROR', index=7, number=101,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='CLIENT_HISTORY', index=8, number=102,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='CLIENT_STATS', index=9, number=103,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='CLIENT_PING', index=10, number=104,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='CLIENT_PONG', index=11, number=105,
-      serialized_options=None,
-      type=None),
-    _descriptor.EnumValueDescriptor(
-      name='CLIENT_ABORT', index=12, number=106,
-      serialized_options=None,
-      type=None),
-  ],
-  containing_type=None,
-  serialized_options=None,
-  serialized_start=554,
-  serialized_end=801,
-)
-_sym_db.RegisterEnumDescriptor(_STOREANDFORWARD_REQUESTRESPONSE)
-
-
-_STOREANDFORWARD_STATISTICS = _descriptor.Descriptor(
-  name='Statistics',
-  full_name='StoreAndForward.Statistics',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='messages_total', full_name='StoreAndForward.Statistics.messages_total', index=0,
-      number=1, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='messages_saved', full_name='StoreAndForward.Statistics.messages_saved', index=1,
-      number=2, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='messages_max', full_name='StoreAndForward.Statistics.messages_max', index=2,
-      number=3, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='up_time', full_name='StoreAndForward.Statistics.up_time', index=3,
-      number=4, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='requests', full_name='StoreAndForward.Statistics.requests', index=4,
-      number=5, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='requests_history', full_name='StoreAndForward.Statistics.requests_history', index=5,
-      number=6, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='heartbeat', full_name='StoreAndForward.Statistics.heartbeat', index=6,
-      number=7, type=8, cpp_type=7, label=1,
-      has_default_value=False, default_value=False,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='return_max', full_name='StoreAndForward.Statistics.return_max', index=7,
-      number=8, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='return_window', full_name='StoreAndForward.Statistics.return_window', index=8,
-      number=9, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=223,
-  serialized_end=428,
-)
-
-_STOREANDFORWARD_HISTORY = _descriptor.Descriptor(
-  name='History',
-  full_name='StoreAndForward.History',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='history_messages', full_name='StoreAndForward.History.history_messages', index=0,
-      number=1, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='window', full_name='StoreAndForward.History.window', index=1,
-      number=2, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='last_request', full_name='StoreAndForward.History.last_request', index=2,
-      number=3, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=430,
-  serialized_end=503,
-)
-
-_STOREANDFORWARD_HEARTBEAT = _descriptor.Descriptor(
-  name='Heartbeat',
-  full_name='StoreAndForward.Heartbeat',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='period', full_name='StoreAndForward.Heartbeat.period', index=0,
-      number=1, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='secondary', full_name='StoreAndForward.Heartbeat.secondary', index=1,
-      number=2, type=13, cpp_type=3, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[],
-  enum_types=[
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=505,
-  serialized_end=551,
-)
-
-_STOREANDFORWARD = _descriptor.Descriptor(
-  name='StoreAndForward',
-  full_name='StoreAndForward',
-  filename=None,
-  file=DESCRIPTOR,
-  containing_type=None,
-  fields=[
-    _descriptor.FieldDescriptor(
-      name='rr', full_name='StoreAndForward.rr', index=0,
-      number=1, type=14, cpp_type=8, label=1,
-      has_default_value=False, default_value=0,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='stats', full_name='StoreAndForward.stats', index=1,
-      number=2, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='history', full_name='StoreAndForward.history', index=2,
-      number=3, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-    _descriptor.FieldDescriptor(
-      name='heartbeat', full_name='StoreAndForward.heartbeat', index=3,
-      number=4, type=11, cpp_type=10, label=1,
-      has_default_value=False, default_value=None,
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR),
-  ],
-  extensions=[
-  ],
-  nested_types=[_STOREANDFORWARD_STATISTICS, _STOREANDFORWARD_HISTORY, _STOREANDFORWARD_HEARTBEAT, ],
-  enum_types=[
-    _STOREANDFORWARD_REQUESTRESPONSE,
-  ],
-  serialized_options=None,
-  is_extendable=False,
-  syntax='proto3',
-  extension_ranges=[],
-  oneofs=[
-  ],
-  serialized_start=23,
-  serialized_end=801,
-)
-
-_STOREANDFORWARD_STATISTICS.containing_type = _STOREANDFORWARD
-_STOREANDFORWARD_HISTORY.containing_type = _STOREANDFORWARD
-_STOREANDFORWARD_HEARTBEAT.containing_type = _STOREANDFORWARD
-_STOREANDFORWARD.fields_by_name['rr'].enum_type = _STOREANDFORWARD_REQUESTRESPONSE
-_STOREANDFORWARD.fields_by_name['stats'].message_type = _STOREANDFORWARD_STATISTICS
-_STOREANDFORWARD.fields_by_name['history'].message_type = _STOREANDFORWARD_HISTORY
-_STOREANDFORWARD.fields_by_name['heartbeat'].message_type = _STOREANDFORWARD_HEARTBEAT
-_STOREANDFORWARD_REQUESTRESPONSE.containing_type = _STOREANDFORWARD
-DESCRIPTOR.message_types_by_name['StoreAndForward'] = _STOREANDFORWARD
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-StoreAndForward = _reflection.GeneratedProtocolMessageType('StoreAndForward', (_message.Message,), {
-
-  'Statistics' : _reflection.GeneratedProtocolMessageType('Statistics', (_message.Message,), {
-    'DESCRIPTOR' : _STOREANDFORWARD_STATISTICS,
-    '__module__' : 'storeforward_pb2'
-    # @@protoc_insertion_point(class_scope:StoreAndForward.Statistics)
-    })
-  ,
-
-  'History' : _reflection.GeneratedProtocolMessageType('History', (_message.Message,), {
-    'DESCRIPTOR' : _STOREANDFORWARD_HISTORY,
-    '__module__' : 'storeforward_pb2'
-    # @@protoc_insertion_point(class_scope:StoreAndForward.History)
-    })
-  ,
-
-  'Heartbeat' : _reflection.GeneratedProtocolMessageType('Heartbeat', (_message.Message,), {
-    'DESCRIPTOR' : _STOREANDFORWARD_HEARTBEAT,
-    '__module__' : 'storeforward_pb2'
-    # @@protoc_insertion_point(class_scope:StoreAndForward.Heartbeat)
-    })
-  ,
-  'DESCRIPTOR' : _STOREANDFORWARD,
-  '__module__' : 'storeforward_pb2'
-  # @@protoc_insertion_point(class_scope:StoreAndForward)
-  })
-_sym_db.RegisterMessage(StoreAndForward)
-_sym_db.RegisterMessage(StoreAndForward.Statistics)
-_sym_db.RegisterMessage(StoreAndForward.History)
-_sym_db.RegisterMessage(StoreAndForward.Heartbeat)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class StoreAndForward -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var CLIENT_ABORT
-
-
-
-
var CLIENT_ERROR
-
-
-
-
var CLIENT_HISTORY
-
-
-
-
var CLIENT_PING
-
-
-
-
var CLIENT_PONG
-
-
-
-
var CLIENT_STATS
-
-
-
-
var DESCRIPTOR
-
-
-
-
var HEARTBEAT_FIELD_NUMBER
-
-
-
-
var HISTORY_FIELD_NUMBER
-
-
-
-
var Heartbeat
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-
-
var History
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-
-
var ROUTER_BUSY
-
-
-
-
var ROUTER_ERROR
-
-
-
-
var ROUTER_HEARTBEAT
-
-
-
-
var ROUTER_HISTORY
-
-
-
-
var ROUTER_PING
-
-
-
-
var ROUTER_PONG
-
-
-
-
var RR_FIELD_NUMBER
-
-
-
-
var RequestResponse
-
-
-
-
var STATS_FIELD_NUMBER
-
-
-
-
var Statistics
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-
-
var UNSET
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var heartbeat
-
-

Getter for heartbeat.

-
- -Expand source code - -
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
-
-
-
var history
-
-

Getter for history.

-
- -Expand source code - -
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
-
-
-
var rr
-
-

Getter for rr.

-
- -Expand source code - -
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)
-
-
-
var stats
-
-

Getter for stats.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/stream_interface.html b/docs/meshtastic/stream_interface.html deleted file mode 100644 index bdec6d7..0000000 --- a/docs/meshtastic/stream_interface.html +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - -meshtastic.stream_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.stream_interface

-
-
-

Stream Interface base class

-
- -Expand source code - -
"""Stream Interface base class
-"""
-import logging
-import threading
-import time
-import traceback
-import serial
-
-
-from .mesh_interface import MeshInterface
-from .util import stripnl
-
-
-START1 = 0x94
-START2 = 0xc3
-HEADER_LEN = 4
-MAX_TO_FROM_RADIO_SIZE = 512
-
-
-class StreamInterface(MeshInterface):
-    """Interface class for meshtastic devices over a stream link (serial, TCP, etc)"""
-
-    def __init__(self, debugOut=None, noProto=False, connectNow=True):
-        """Constructor, opens a connection to self.stream
-
-        Keyword Arguments:
-            debugOut {stream} -- If a stream is provided, any debug serial output from the
-                                 device will be emitted to that stream. (default: {None})
-
-        Raises:
-            Exception: [description]
-            Exception: [description]
-        """
-
-        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)
-
-        MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
-
-        # Start the reader thread after superclass constructor completes init
-        if connectNow:
-            self.connect()
-            if not noProto:
-                self.waitForConfig()
-
-    def connect(self):
-        """Connect to our radio
-
-        Normally this is called automatically by the constructor, but if you
-        passed in connectNow=False you can manually start the reading thread later.
-        """
-
-        # Send some bogus UART characters to force a sleeping device to wake, and
-        # if the reading statemachine was parsing a bad packet make sure
-        # we write enought start bytes to force it to resync (we don't use START1
-        # because we want to ensure it is looking for START1)
-        p = bytearray([START2] * 32)
-        self._writeBytes(p)
-        time.sleep(0.1)  # wait 100ms to give device time to start running
-
-        self._rxThread.start()
-
-        self._startConfig()
-
-        if not self.noProto:  # Wait for the db download if using the protocol
-            self._waitConnected()
-
-    def _disconnected(self):
-        """We override the superclass implementation to close our port"""
-        MeshInterface._disconnected(self)
-
-        logging.debug("Closing our port")
-        # pylint: disable=E0203
-        if not self.stream is None:
-            # pylint: disable=E0203
-            self.stream.close()
-            # pylint: disable=W0201
-            self.stream = None
-
-    def _writeBytes(self, b):
-        """Write an array of bytes to our stream and flush"""
-        if self.stream:  # ignore writes when stream is closed
-            self.stream.write(b)
-            self.stream.flush()
-
-    def _readBytes(self, length):
-        """Read an array of bytes from our stream"""
-        if self.stream:
-            return self.stream.read(length)
-        else:
-            return None
-
-    def _sendToRadioImpl(self, toRadio):
-        """Send a ToRadio protobuf to the device"""
-        logging.debug(f"Sending: {stripnl(toRadio)}")
-        b = toRadio.SerializeToString()
-        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):
-        """Close a connection to the device"""
-        logging.debug("Closing stream")
-        MeshInterface.close(self)
-        # pyserial cancel_read doesn't seem to work, therefore we ask the
-        # reader thread to close things for us
-        self._wantExit = True
-        if self._rxThread != threading.current_thread():
-            self._rxThread.join()  # wait for it to exit
-
-    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")
-                b = self._readBytes(1)
-                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
-                    self._rxBuf = self._rxBuf + b
-
-                    if ptr == 0:  # looking for START1
-                        if c != START1:
-                            self._rxBuf = empty  # failed to find start
-                            if self.debugOut is not None:
-                                try:
-                                    self.debugOut.write(b.decode("utf-8"))
-                                except:
-                                    self.debugOut.write('?')
-
-                    elif ptr == 1:  # looking for START2
-                        if c != START2:
-                            self._rxBuf = empty  # failed to find start2
-                    elif ptr >= HEADER_LEN - 1:  # we've at least got a 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 was out out bounds, restart
-
-                        if len(self._rxBuf) != 0 and ptr + 1 >= packetlen + HEADER_LEN:
-                            try:
-                                self._handleFromRadio(self._rxBuf[HEADER_LEN:])
-                            except Exception as ex:
-                                logging.error(f"Error while handling message from radio {ex}")
-                                traceback.print_exc()
-                            self._rxBuf = empty
-                else:
-                    # logging.debug(f"timeout")
-                    pass
-        except serial.SerialException as ex:
-            if not self._wantExit:  # We might intentionally get an exception during shutdown
-                logging.warning(f"Meshtastic serial port disconnected, disconnecting... {ex}")
-        except OSError as ex:
-            if not self._wantExit:  # We might intentionally get an exception during shutdown
-                logging.error(f"Unexpected OSError, terminating meshtastic reader... {ex}")
-        except Exception as ex:
-            logging.error(f"Unexpected exception, terminating meshtastic reader... {ex}")
-        finally:
-            logging.debug("reader is exiting")
-            self._disconnected()
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class StreamInterface -(debugOut=None, noProto=False, connectNow=True) -
-
-

Interface class for meshtastic devices over a stream link (serial, TCP, etc)

-

Constructor, opens a connection to self.stream

-

Keyword Arguments: -debugOut {stream} – If a stream is provided, any debug serial output from the -device will be emitted to that stream. (default: {None})

-

Raises

-
-
Exception
-
[description]
-
Exception
-
[description]
-
-
- -Expand source code - -
class StreamInterface(MeshInterface):
-    """Interface class for meshtastic devices over a stream link (serial, TCP, etc)"""
-
-    def __init__(self, debugOut=None, noProto=False, connectNow=True):
-        """Constructor, opens a connection to self.stream
-
-        Keyword Arguments:
-            debugOut {stream} -- If a stream is provided, any debug serial output from the
-                                 device will be emitted to that stream. (default: {None})
-
-        Raises:
-            Exception: [description]
-            Exception: [description]
-        """
-
-        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)
-
-        MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
-
-        # Start the reader thread after superclass constructor completes init
-        if connectNow:
-            self.connect()
-            if not noProto:
-                self.waitForConfig()
-
-    def connect(self):
-        """Connect to our radio
-
-        Normally this is called automatically by the constructor, but if you
-        passed in connectNow=False you can manually start the reading thread later.
-        """
-
-        # Send some bogus UART characters to force a sleeping device to wake, and
-        # if the reading statemachine was parsing a bad packet make sure
-        # we write enought start bytes to force it to resync (we don't use START1
-        # because we want to ensure it is looking for START1)
-        p = bytearray([START2] * 32)
-        self._writeBytes(p)
-        time.sleep(0.1)  # wait 100ms to give device time to start running
-
-        self._rxThread.start()
-
-        self._startConfig()
-
-        if not self.noProto:  # Wait for the db download if using the protocol
-            self._waitConnected()
-
-    def _disconnected(self):
-        """We override the superclass implementation to close our port"""
-        MeshInterface._disconnected(self)
-
-        logging.debug("Closing our port")
-        # pylint: disable=E0203
-        if not self.stream is None:
-            # pylint: disable=E0203
-            self.stream.close()
-            # pylint: disable=W0201
-            self.stream = None
-
-    def _writeBytes(self, b):
-        """Write an array of bytes to our stream and flush"""
-        if self.stream:  # ignore writes when stream is closed
-            self.stream.write(b)
-            self.stream.flush()
-
-    def _readBytes(self, length):
-        """Read an array of bytes from our stream"""
-        if self.stream:
-            return self.stream.read(length)
-        else:
-            return None
-
-    def _sendToRadioImpl(self, toRadio):
-        """Send a ToRadio protobuf to the device"""
-        logging.debug(f"Sending: {stripnl(toRadio)}")
-        b = toRadio.SerializeToString()
-        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):
-        """Close a connection to the device"""
-        logging.debug("Closing stream")
-        MeshInterface.close(self)
-        # pyserial cancel_read doesn't seem to work, therefore we ask the
-        # reader thread to close things for us
-        self._wantExit = True
-        if self._rxThread != threading.current_thread():
-            self._rxThread.join()  # wait for it to exit
-
-    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")
-                b = self._readBytes(1)
-                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
-                    self._rxBuf = self._rxBuf + b
-
-                    if ptr == 0:  # looking for START1
-                        if c != START1:
-                            self._rxBuf = empty  # failed to find start
-                            if self.debugOut is not None:
-                                try:
-                                    self.debugOut.write(b.decode("utf-8"))
-                                except:
-                                    self.debugOut.write('?')
-
-                    elif ptr == 1:  # looking for START2
-                        if c != START2:
-                            self._rxBuf = empty  # failed to find start2
-                    elif ptr >= HEADER_LEN - 1:  # we've at least got a 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 was out out bounds, restart
-
-                        if len(self._rxBuf) != 0 and ptr + 1 >= packetlen + HEADER_LEN:
-                            try:
-                                self._handleFromRadio(self._rxBuf[HEADER_LEN:])
-                            except Exception as ex:
-                                logging.error(f"Error while handling message from radio {ex}")
-                                traceback.print_exc()
-                            self._rxBuf = empty
-                else:
-                    # logging.debug(f"timeout")
-                    pass
-        except serial.SerialException as ex:
-            if not self._wantExit:  # We might intentionally get an exception during shutdown
-                logging.warning(f"Meshtastic serial port disconnected, disconnecting... {ex}")
-        except OSError as ex:
-            if not self._wantExit:  # We might intentionally get an exception during shutdown
-                logging.error(f"Unexpected OSError, terminating meshtastic reader... {ex}")
-        except Exception as ex:
-            logging.error(f"Unexpected exception, terminating meshtastic reader... {ex}")
-        finally:
-            logging.debug("reader is exiting")
-            self._disconnected()
-
-

Ancestors

- -

Subclasses

- -

Methods

-
-
-def close(self) -
-
-

Close a connection to the device

-
- -Expand source code - -
def close(self):
-    """Close a connection to the device"""
-    logging.debug("Closing stream")
-    MeshInterface.close(self)
-    # pyserial cancel_read doesn't seem to work, therefore we ask the
-    # reader thread to close things for us
-    self._wantExit = True
-    if self._rxThread != threading.current_thread():
-        self._rxThread.join()  # wait for it to exit
-
-
-
-def connect(self) -
-
-

Connect to our radio

-

Normally this is called automatically by the constructor, but if you -passed in connectNow=False you can manually start the reading thread later.

-
- -Expand source code - -
def connect(self):
-    """Connect to our radio
-
-    Normally this is called automatically by the constructor, but if you
-    passed in connectNow=False you can manually start the reading thread later.
-    """
-
-    # Send some bogus UART characters to force a sleeping device to wake, and
-    # if the reading statemachine was parsing a bad packet make sure
-    # we write enought start bytes to force it to resync (we don't use START1
-    # because we want to ensure it is looking for START1)
-    p = bytearray([START2] * 32)
-    self._writeBytes(p)
-    time.sleep(0.1)  # wait 100ms to give device time to start running
-
-    self._rxThread.start()
-
-    self._startConfig()
-
-    if not self.noProto:  # Wait for the db download if using the protocol
-        self._waitConnected()
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tcp_interface.html b/docs/meshtastic/tcp_interface.html deleted file mode 100644 index 1ea7d18..0000000 --- a/docs/meshtastic/tcp_interface.html +++ /dev/null @@ -1,251 +0,0 @@ - - - - - - -meshtastic.tcp_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tcp_interface

-
-
-

TCPInterface class for interfacing with http endpoint

-
- -Expand source code - -
"""TCPInterface class for interfacing with http endpoint
-"""
-import logging
-import socket
-from typing import AnyStr
-
-from .stream_interface import StreamInterface
-
-class TCPInterface(StreamInterface):
-    """Interface class for meshtastic devices over a TCP link"""
-
-    def __init__(self, hostname: AnyStr, debugOut=None, noProto=False,
-                 connectNow=True, portNumber=4403):
-        """Constructor, opens a connection to a specified IP address/hostname
-
-        Keyword Arguments:
-            hostname {string} -- Hostname/IP address of the device to connect to
-        """
-
-        # Instead of wrapping as a stream, we use the native socket API
-        # self.stream = sock.makefile('rw')
-        self.stream = None
-
-        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"""
-        logging.debug("Closing TCP stream")
-        StreamInterface.close(self)
-        # Sometimes the socket read might be blocked in the reader thread.
-        # Therefore we force the shutdown by closing the socket here
-        self._wantExit = True
-        if not self.socket is None:
-            try:
-                self.socket.shutdown(socket.SHUT_RDWR)
-            except:
-                pass  # Ignore errors in shutdown, because we might have a race with the server
-            self.socket.close()
-
-    def _writeBytes(self, b):
-        """Write an array of bytes to our stream and flush"""
-        self.socket.send(b)
-
-    def _readBytes(self, length):
-        """Read an array of bytes from our stream"""
-        return self.socket.recv(length)
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class TCPInterface -(hostname: ~AnyStr, debugOut=None, noProto=False, connectNow=True, portNumber=4403) -
-
-

Interface class for meshtastic devices over a TCP link

-

Constructor, opens a connection to a specified IP address/hostname

-

Keyword Arguments: -hostname {string} – Hostname/IP address of the device to connect to

-
- -Expand source code - -
class TCPInterface(StreamInterface):
-    """Interface class for meshtastic devices over a TCP link"""
-
-    def __init__(self, hostname: AnyStr, debugOut=None, noProto=False,
-                 connectNow=True, portNumber=4403):
-        """Constructor, opens a connection to a specified IP address/hostname
-
-        Keyword Arguments:
-            hostname {string} -- Hostname/IP address of the device to connect to
-        """
-
-        # Instead of wrapping as a stream, we use the native socket API
-        # self.stream = sock.makefile('rw')
-        self.stream = None
-
-        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"""
-        logging.debug("Closing TCP stream")
-        StreamInterface.close(self)
-        # Sometimes the socket read might be blocked in the reader thread.
-        # Therefore we force the shutdown by closing the socket here
-        self._wantExit = True
-        if not self.socket is None:
-            try:
-                self.socket.shutdown(socket.SHUT_RDWR)
-            except:
-                pass  # Ignore errors in shutdown, because we might have a race with the server
-            self.socket.close()
-
-    def _writeBytes(self, b):
-        """Write an array of bytes to our stream and flush"""
-        self.socket.send(b)
-
-    def _readBytes(self, length):
-        """Read an array of bytes from our stream"""
-        return self.socket.recv(length)
-
-

Ancestors

- -

Methods

-
-
-def myConnect(self) -
-
-

Connect to socket

-
- -Expand source code - -
def myConnect(self):
-    """Connect to socket"""
-    server_address = (self.hostname, self.portNumber)
-    sock = socket.create_connection(server_address)
-    self.socket = sock
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/test.html b/docs/meshtastic/test.html deleted file mode 100644 index 0374767..0000000 --- a/docs/meshtastic/test.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - - - -meshtastic.test API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.test

-
-
-

With two radios connected serially, send and receive test -messages and report back if successful.

-
- -Expand source code - -
"""With two radios connected serially, send and receive test
-   messages and report back if successful.
-"""
-import logging
-import time
-import sys
-import traceback
-from dotmap import DotMap
-from pubsub import pub
-import meshtastic.util
-from .__init__ import BROADCAST_NUM
-from .serial_interface import SerialInterface
-from .tcp_interface import TCPInterface
-
-
-"""The interfaces we are using for our tests"""
-interfaces = None
-
-"""A list of all packets we received while the current test was running"""
-receivedPackets = None
-
-testsRunning = False
-
-testNumber = 0
-
-sendingInterface = None
-
-
-def onReceive(packet, interface):
-    """Callback invoked when a packet arrives"""
-    if sendingInterface == interface:
-        pass
-        # print("Ignoring sending interface")
-    else:
-        # print(f"From {interface.stream.port}: {packet}")
-        p = DotMap(packet)
-
-        if p.decoded.portnum == "TEXT_MESSAGE_APP":
-            # We only care a about clear text packets
-            if receivedPackets is not None:
-                receivedPackets.append(p)
-
-
-def onNode(node):
-    """Callback invoked when the node DB changes"""
-    print(f"Node changed: {node}")
-
-
-def subscribe():
-    """Subscribe to the topics the user probably wants to see, prints output to stdout"""
-
-    pub.subscribe(onNode, "meshtastic.node")
-
-
-def testSend(fromInterface, toInterface, isBroadcast=False, asBinary=False, wantAck=False):
-    """
-    Sends one test packet between two nodes and then returns success or failure
-
-    Arguments:
-        fromInterface {[type]} -- [description]
-        toInterface {[type]} -- [description]
-
-    Returns:
-        boolean -- True for success
-    """
-    global receivedPackets
-    receivedPackets = []
-    fromNode = fromInterface.myInfo.my_node_num
-
-    if isBroadcast:
-        toNode = BROADCAST_NUM
-    else:
-        toNode = toInterface.myInfo.my_node_num
-
-    logging.debug(
-        f"Sending test wantAck={wantAck} packet from {fromNode} to {toNode}")
-    global sendingInterface
-    sendingInterface = fromInterface
-    if not asBinary:
-        fromInterface.sendText(f"Test {testNumber}", toNode, wantAck=wantAck)
-    else:
-        fromInterface.sendData((f"Binary {testNumber}").encode(
-            "utf-8"), toNode, wantAck=wantAck)
-    for _ in range(60):  # max of 60 secs before we timeout
-        time.sleep(1)
-        if  len(receivedPackets) >= 1:
-            return True
-    return False  # Failed to send
-
-
-def runTests(numTests=50, wantAck=False, maxFailures=0):
-    """Run the tests."""
-    logging.info(f"Running {numTests} tests with wantAck={wantAck}")
-    numFail = 0
-    numSuccess = 0
-    for _ in range(numTests):
-        global testNumber
-        testNumber = testNumber + 1
-        isBroadcast = True
-        # asBinary=(i % 2 == 0)
-        success = testSend(
-            interfaces[0], interfaces[1], isBroadcast, asBinary=False, wantAck=wantAck)
-        if not success:
-            numFail = numFail + 1
-            logging.error(
-                f"Test {testNumber} failed, expected packet not received ({numFail} failures so far)")
-        else:
-            numSuccess = numSuccess + 1
-            logging.info(
-                f"Test {testNumber} succeeded {numSuccess} successes {numFail} failures so far")
-
-        time.sleep(1)
-
-    if numFail > maxFailures:
-        logging.error("Too many failures! Test failed!")
-        return False
-    return True
-
-
-def testThread(numTests=50):
-    """Test thread"""
-    logging.info("Found devices, starting tests...")
-    result = runTests(numTests, wantAck=True)
-    if result:
-        # Run another test
-        # Allow a few dropped packets
-        result = runTests(numTests, wantAck=False, maxFailures=1)
-    return result
-
-
-def onConnection(topic=pub.AUTO_TOPIC):
-    """Callback invoked when we connect/disconnect from a radio"""
-    print(f"Connection changed: {topic.getName()}")
-
-
-def openDebugLog(portName):
-    """Open the debug log file"""
-    debugname = "log" + portName.replace("/", "_")
-    logging.info(f"Writing serial debugging to {debugname}")
-    return open(debugname, 'w+', buffering=1, encoding='utf8')
-
-
-def testAll(numTests=5):
-    """
-    Run a series of tests using devices we can find.
-    This is called from the cli with the "--test" option.
-
-    """
-    ports = meshtastic.util.findPorts()
-    if len(ports) < 2:
-        meshtastic.util.our_exit("Warning: Must have at least two devices connected to USB.")
-
-    pub.subscribe(onConnection, "meshtastic.connection")
-    pub.subscribe(onReceive, "meshtastic.receive")
-    global interfaces
-    interfaces = list(map(lambda port: SerialInterface(
-        port, debugOut=openDebugLog(port), connectNow=True), ports))
-
-    logging.info("Ports opened, starting test")
-    result = testThread(numTests)
-
-    for i in interfaces:
-        i.close()
-
-    return result
-
-
-def testSimulator():
-    """
-    Assume that someone has launched meshtastic-native as a simulated node.
-    Talk to that node over TCP, do some operations and if they are successful
-    exit the process with a success code, else exit with a non zero exit code.
-
-    Run with
-    python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
-    """
-    logging.basicConfig(level=logging.DEBUG)
-    logging.info("Connecting to simulator on localhost!")
-    try:
-        iface = TCPInterface("localhost")
-        iface.showInfo()
-        iface.localNode.showInfo()
-        iface.localNode.exitSimulator()
-        iface.close()
-        logging.info("Integration test successful!")
-    except:
-        print("Error while testing simulator:", sys.exc_info()[0])
-        traceback.print_exc()
-        sys.exit(1)
-    sys.exit(0)
-
-
-
-
-
-

Global variables

-
-
var interfaces
-
-

A list of all packets we received while the current test was running

-
-
-
-
-

Functions

-
-
-def onConnection(topic=pubsub.core.callables.AUTO_TOPIC) -
-
-

Callback invoked when we connect/disconnect from a radio

-
- -Expand source code - -
def onConnection(topic=pub.AUTO_TOPIC):
-    """Callback invoked when we connect/disconnect from a radio"""
-    print(f"Connection changed: {topic.getName()}")
-
-
-
-def onNode(node) -
-
-

Callback invoked when the node DB changes

-
- -Expand source code - -
def onNode(node):
-    """Callback invoked when the node DB changes"""
-    print(f"Node changed: {node}")
-
-
-
-def onReceive(packet, interface) -
-
-

Callback invoked when a packet arrives

-
- -Expand source code - -
def onReceive(packet, interface):
-    """Callback invoked when a packet arrives"""
-    if sendingInterface == interface:
-        pass
-        # print("Ignoring sending interface")
-    else:
-        # print(f"From {interface.stream.port}: {packet}")
-        p = DotMap(packet)
-
-        if p.decoded.portnum == "TEXT_MESSAGE_APP":
-            # We only care a about clear text packets
-            if receivedPackets is not None:
-                receivedPackets.append(p)
-
-
-
-def openDebugLog(portName) -
-
-

Open the debug log file

-
- -Expand source code - -
def openDebugLog(portName):
-    """Open the debug log file"""
-    debugname = "log" + portName.replace("/", "_")
-    logging.info(f"Writing serial debugging to {debugname}")
-    return open(debugname, 'w+', buffering=1, encoding='utf8')
-
-
-
-def runTests(numTests=50, wantAck=False, maxFailures=0) -
-
-

Run the tests.

-
- -Expand source code - -
def runTests(numTests=50, wantAck=False, maxFailures=0):
-    """Run the tests."""
-    logging.info(f"Running {numTests} tests with wantAck={wantAck}")
-    numFail = 0
-    numSuccess = 0
-    for _ in range(numTests):
-        global testNumber
-        testNumber = testNumber + 1
-        isBroadcast = True
-        # asBinary=(i % 2 == 0)
-        success = testSend(
-            interfaces[0], interfaces[1], isBroadcast, asBinary=False, wantAck=wantAck)
-        if not success:
-            numFail = numFail + 1
-            logging.error(
-                f"Test {testNumber} failed, expected packet not received ({numFail} failures so far)")
-        else:
-            numSuccess = numSuccess + 1
-            logging.info(
-                f"Test {testNumber} succeeded {numSuccess} successes {numFail} failures so far")
-
-        time.sleep(1)
-
-    if numFail > maxFailures:
-        logging.error("Too many failures! Test failed!")
-        return False
-    return True
-
-
-
-def subscribe() -
-
-

Subscribe to the topics the user probably wants to see, prints output to stdout

-
- -Expand source code - -
def subscribe():
-    """Subscribe to the topics the user probably wants to see, prints output to stdout"""
-
-    pub.subscribe(onNode, "meshtastic.node")
-
-
-
-def testAll(numTests=5) -
-
-

Run a series of tests using devices we can find. -This is called from the cli with the "–test" option.

-
- -Expand source code - -
def testAll(numTests=5):
-    """
-    Run a series of tests using devices we can find.
-    This is called from the cli with the "--test" option.
-
-    """
-    ports = meshtastic.util.findPorts()
-    if len(ports) < 2:
-        meshtastic.util.our_exit("Warning: Must have at least two devices connected to USB.")
-
-    pub.subscribe(onConnection, "meshtastic.connection")
-    pub.subscribe(onReceive, "meshtastic.receive")
-    global interfaces
-    interfaces = list(map(lambda port: SerialInterface(
-        port, debugOut=openDebugLog(port), connectNow=True), ports))
-
-    logging.info("Ports opened, starting test")
-    result = testThread(numTests)
-
-    for i in interfaces:
-        i.close()
-
-    return result
-
-
-
-def testSend(fromInterface, toInterface, isBroadcast=False, asBinary=False, wantAck=False) -
-
-

Sends one test packet between two nodes and then returns success or failure

-

Arguments

-

fromInterface {[type]} – [description] -toInterface {[type]} – [description]

-

Returns

-

boolean – True for success

-
- -Expand source code - -
def testSend(fromInterface, toInterface, isBroadcast=False, asBinary=False, wantAck=False):
-    """
-    Sends one test packet between two nodes and then returns success or failure
-
-    Arguments:
-        fromInterface {[type]} -- [description]
-        toInterface {[type]} -- [description]
-
-    Returns:
-        boolean -- True for success
-    """
-    global receivedPackets
-    receivedPackets = []
-    fromNode = fromInterface.myInfo.my_node_num
-
-    if isBroadcast:
-        toNode = BROADCAST_NUM
-    else:
-        toNode = toInterface.myInfo.my_node_num
-
-    logging.debug(
-        f"Sending test wantAck={wantAck} packet from {fromNode} to {toNode}")
-    global sendingInterface
-    sendingInterface = fromInterface
-    if not asBinary:
-        fromInterface.sendText(f"Test {testNumber}", toNode, wantAck=wantAck)
-    else:
-        fromInterface.sendData((f"Binary {testNumber}").encode(
-            "utf-8"), toNode, wantAck=wantAck)
-    for _ in range(60):  # max of 60 secs before we timeout
-        time.sleep(1)
-        if  len(receivedPackets) >= 1:
-            return True
-    return False  # Failed to send
-
-
-
-def testSimulator() -
-
-

Assume that someone has launched meshtastic-native as a simulated node. -Talk to that node over TCP, do some operations and if they are successful -exit the process with a success code, else exit with a non zero exit code.

-

Run with -python3 -c 'from meshtastic.test import testSimulator; testSimulator()'

-
- -Expand source code - -
def testSimulator():
-    """
-    Assume that someone has launched meshtastic-native as a simulated node.
-    Talk to that node over TCP, do some operations and if they are successful
-    exit the process with a success code, else exit with a non zero exit code.
-
-    Run with
-    python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
-    """
-    logging.basicConfig(level=logging.DEBUG)
-    logging.info("Connecting to simulator on localhost!")
-    try:
-        iface = TCPInterface("localhost")
-        iface.showInfo()
-        iface.localNode.showInfo()
-        iface.localNode.exitSimulator()
-        iface.close()
-        logging.info("Integration test successful!")
-    except:
-        print("Error while testing simulator:", sys.exc_info()[0])
-        traceback.print_exc()
-        sys.exit(1)
-    sys.exit(0)
-
-
-
-def testThread(numTests=50) -
-
-

Test thread

-
- -Expand source code - -
def testThread(numTests=50):
-    """Test thread"""
-    logging.info("Found devices, starting tests...")
-    result = runTests(numTests, wantAck=True)
-    if result:
-        # Run another test
-        # Allow a few dropped packets
-        result = runTests(numTests, wantAck=False, maxFailures=1)
-    return result
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/conftest.html b/docs/meshtastic/tests/conftest.html deleted file mode 100644 index efb42ff..0000000 --- a/docs/meshtastic/tests/conftest.html +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - -meshtastic.tests.conftest API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.conftest

-
-
-

Common pytest code (place for fixtures).

-
- -Expand source code - -
"""Common pytest code (place for fixtures)."""
-
-import argparse
-
-from unittest.mock import MagicMock
-import pytest
-
-from meshtastic.__main__ import Globals
-from ..mesh_interface import MeshInterface
-
-
-@pytest.fixture
-def reset_globals():
-    """Fixture to reset globals."""
-    parser = None
-    parser = argparse.ArgumentParser()
-    Globals.getInstance().reset()
-    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
-
-
-
-
-
-
-
-

Functions

-
-
-def iface_with_nodes() -
-
-

Fixture to setup some nodes.

-
- -Expand source code - -
@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
-
-
-
-def reset_globals() -
-
-

Fixture to reset globals.

-
- -Expand source code - -
@pytest.fixture
-def reset_globals():
-    """Fixture to reset globals."""
-    parser = None
-    parser = argparse.ArgumentParser()
-    Globals.getInstance().reset()
-    Globals.getInstance().set_parser(parser)
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/index.html b/docs/meshtastic/tests/index.html deleted file mode 100644 index b755e53..0000000 --- a/docs/meshtastic/tests/index.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - -meshtastic.tests API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests

-
-
-
-
-

Sub-modules

-
-
meshtastic.tests.conftest
-
-

Common pytest code (place for fixtures).

-
-
meshtastic.tests.test_ble_interface
-
-

Meshtastic unit tests for ble_interface.py

-
-
meshtastic.tests.test_examples
-
-

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: …

-
-
meshtastic.tests.test_globals
-
-

Meshtastic unit tests for globals.py

-
-
meshtastic.tests.test_int
-
-

Meshtastic integration tests

-
-
meshtastic.tests.test_main
-
-

Meshtastic unit tests for main.py

-
-
meshtastic.tests.test_mesh_interface
-
-

Meshtastic unit tests for mesh_interface.py

-
-
meshtastic.tests.test_node
-
-

Meshtastic unit tests for node.py

-
-
meshtastic.tests.test_remote_hardware
-
-

Meshtastic unit tests for remote_hardware.py

-
-
meshtastic.tests.test_serial_interface
-
-

Meshtastic unit tests for serial_interface.py

-
-
meshtastic.tests.test_smoke1
-
-

Meshtastic smoke tests with a single device via USB

-
-
meshtastic.tests.test_smoke2
-
-

Meshtastic smoke tests with 2 devices connected via USB

-
-
meshtastic.tests.test_smoke_wifi
-
-

Meshtastic smoke tests a device setup with wifi …

-
-
meshtastic.tests.test_stream_interface
-
-

Meshtastic unit tests for stream_interface.py

-
-
meshtastic.tests.test_tcp_interface
-
-

Meshtastic unit tests for tcp_interface.py

-
-
meshtastic.tests.test_util
-
-

Meshtastic unit tests for util.py

-
-
-
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_ble_interface.html b/docs/meshtastic/tests/test_ble_interface.html deleted file mode 100644 index ae87dd6..0000000 --- a/docs/meshtastic/tests/test_ble_interface.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - -meshtastic.tests.test_ble_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_ble_interface

-
-
-

Meshtastic unit tests for ble_interface.py

-
- -Expand source code - -
"""Meshtastic unit tests for ble_interface.py"""
-
-
-import pytest
-
-from ..ble_interface import BLEInterface
-
-@pytest.mark.unit
-def test_BLEInterface():
-    """Test that we can instantiate a BLEInterface"""
-    iface = BLEInterface('foo', debugOut=True, noProto=True)
-    iface.close()
-
-
-
-
-
-
-
-

Functions

-
-
-def test_BLEInterface() -
-
-

Test that we can instantiate a BLEInterface

-
- -Expand source code - -
@pytest.mark.unit
-def test_BLEInterface():
-    """Test that we can instantiate a BLEInterface"""
-    iface = BLEInterface('foo', debugOut=True, noProto=True)
-    iface.close()
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_examples.html b/docs/meshtastic/tests/test_examples.html deleted file mode 100644 index 6d35c14..0000000 --- a/docs/meshtastic/tests/test_examples.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - -meshtastic.tests.test_examples API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_examples

-
-
-

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 ."

-
- -Expand source code - -
"""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.'
-
-
-
-
-
-
-
-

Functions

-
-
-def test_examples_hello_world_serial_no_arg() -
-
-

Test hello_world_serial without any args

-
- -Expand source code - -
@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
-
-
-
-def test_examples_hello_world_serial_with_arg(capsys) -
-
-

Test hello_world_serial with arg

-
- -Expand source code - -
@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.'
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_globals.html b/docs/meshtastic/tests/test_globals.html deleted file mode 100644 index df7d4e9..0000000 --- a/docs/meshtastic/tests/test_globals.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - -meshtastic.tests.test_globals API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_globals

-
-
-

Meshtastic unit tests for globals.py

-
- -Expand source code - -
"""Meshtastic unit tests for globals.py
-"""
-
-import pytest
-
-from ..globals import Globals
-
-
-@pytest.mark.unit
-def test_globals_get_instaance():
-    """Test that we can instantiate a Globals instance"""
-    ourglobals = Globals.getInstance()
-    ourglobals2 = Globals.getInstance()
-    assert ourglobals == ourglobals2
-
-
-@pytest.mark.unit
-def test_globals_there_can_be_only_one():
-    """Test that we can cannot create two Globals instances"""
-    # if we have an instance, delete it
-    Globals.getInstance()
-    with pytest.raises(Exception) as pytest_wrapped_e:
-        # try to create another instance
-        Globals()
-    assert pytest_wrapped_e.type == Exception
-
-
-
-
-
-
-
-

Functions

-
-
-def test_globals_get_instaance() -
-
-

Test that we can instantiate a Globals instance

-
- -Expand source code - -
@pytest.mark.unit
-def test_globals_get_instaance():
-    """Test that we can instantiate a Globals instance"""
-    ourglobals = Globals.getInstance()
-    ourglobals2 = Globals.getInstance()
-    assert ourglobals == ourglobals2
-
-
-
-def test_globals_there_can_be_only_one() -
-
-

Test that we can cannot create two Globals instances

-
- -Expand source code - -
@pytest.mark.unit
-def test_globals_there_can_be_only_one():
-    """Test that we can cannot create two Globals instances"""
-    # if we have an instance, delete it
-    Globals.getInstance()
-    with pytest.raises(Exception) as pytest_wrapped_e:
-        # try to create another instance
-        Globals()
-    assert pytest_wrapped_e.type == Exception
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_int.html b/docs/meshtastic/tests/test_int.html deleted file mode 100644 index 4811aad..0000000 --- a/docs/meshtastic/tests/test_int.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - -meshtastic.tests.test_int API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_int

-
-
-

Meshtastic integration tests

-
- -Expand source code - -
"""Meshtastic integration tests"""
-import re
-import subprocess
-
-import pytest
-
-
-@pytest.mark.int
-def test_int_no_args():
-    """Test without any args"""
-    return_value, out = subprocess.getstatusoutput('meshtastic')
-    assert re.match(r'usage: meshtastic', out)
-    assert return_value == 1
-
-
-@pytest.mark.int
-def test_int_version():
-    """Test '--version'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --version')
-    assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
-    assert return_value == 0
-
-
-@pytest.mark.int
-def test_int_help():
-    """Test '--help'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --help')
-    assert re.match(r'usage: meshtastic ', out)
-    assert return_value == 0
-
-
-@pytest.mark.int
-def test_int_support():
-    """Test '--support'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --support')
-    assert re.search(r'System', out)
-    assert re.search(r'Python', out)
-    assert return_value == 0
-
-
-
-
-
-
-
-

Functions

-
-
-def test_int_help() -
-
-

Test '–help'.

-
- -Expand source code - -
@pytest.mark.int
-def test_int_help():
-    """Test '--help'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --help')
-    assert re.match(r'usage: meshtastic ', out)
-    assert return_value == 0
-
-
-
-def test_int_no_args() -
-
-

Test without any args

-
- -Expand source code - -
@pytest.mark.int
-def test_int_no_args():
-    """Test without any args"""
-    return_value, out = subprocess.getstatusoutput('meshtastic')
-    assert re.match(r'usage: meshtastic', out)
-    assert return_value == 1
-
-
-
-def test_int_support() -
-
-

Test '–support'.

-
- -Expand source code - -
@pytest.mark.int
-def test_int_support():
-    """Test '--support'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --support')
-    assert re.search(r'System', out)
-    assert re.search(r'Python', out)
-    assert return_value == 0
-
-
-
-def test_int_version() -
-
-

Test '–version'.

-
- -Expand source code - -
@pytest.mark.int
-def test_int_version():
-    """Test '--version'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --version')
-    assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
-    assert return_value == 0
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_main.html b/docs/meshtastic/tests/test_main.html deleted file mode 100644 index c9a0f51..0000000 --- a/docs/meshtastic/tests/test_main.html +++ /dev/null @@ -1,4552 +0,0 @@ - - - - - - -meshtastic.tests.test_main API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_main

-
-
-

Meshtastic unit tests for main.py

-
- -Expand source code - -
"""Meshtastic unit tests for __main__.py"""
-# pylint: disable=C0302
-
-import sys
-import os
-import re
-import logging
-
-from unittest.mock import patch, MagicMock
-import pytest
-
-from meshtastic.__main__ import initParser, main, Globals, onReceive, onConnection, export_config, getPref, setPref
-#from ..radioconfig_pb2 import UserPreferences
-import meshtastic.radioconfig_pb2
-from ..serial_interface import SerialInterface
-from ..tcp_interface import TCPInterface
-from ..ble_interface import BLEInterface
-from ..node import Node
-from ..channel_pb2 import Channel
-from ..remote_hardware import onGPIOreceive
-
-
-@pytest.mark.unit
-def test_main_init_parser_no_args(capsys, reset_globals):
-    """Test no arguments"""
-    sys.argv = ['']
-    Globals.getInstance().set_args(sys.argv)
-    initParser()
-    out, err = capsys.readouterr()
-    assert out == ''
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_main_init_parser_version(capsys, reset_globals):
-    """Test --version"""
-    sys.argv = ['', '--version']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        initParser()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-    out, err = capsys.readouterr()
-    assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_main_main_version(capsys, reset_globals):
-    """Test --version"""
-    sys.argv = ['', '--version']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-    out, err = capsys.readouterr()
-    assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_main_main_no_args(reset_globals):
-    """Test with no args"""
-    sys.argv = ['']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-@pytest.mark.unit
-def test_main_support(capsys, reset_globals):
-    """Test --support"""
-    sys.argv = ['', '--support']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-    out, err = capsys.readouterr()
-    assert re.search(r'System', out, re.MULTILINE)
-    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 == ''
-
-
-@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=[])
-def test_main_ch_index_no_devices(patched_find_ports, capsys, reset_globals):
-    """Test --ch-index 1"""
-    sys.argv = ['', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert Globals.getInstance().get_channel_index() == 1
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: No Meshtastic devices detected', out, re.MULTILINE)
-    assert err == ''
-    patched_find_ports.assert_called()
-
-
-@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=[])
-def test_main_test_no_ports(patched_find_ports, reset_globals):
-    """Test --test with no hardware"""
-    sys.argv = ['', '--test']
-    Globals.getInstance().set_args(sys.argv)
-
-    assert Globals.getInstance().get_target_node() is None
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    patched_find_ports.assert_called()
-
-
-@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyFake1'])
-def test_main_test_one_port(patched_find_ports, reset_globals):
-    """Test --test with one fake port"""
-    sys.argv = ['', '--test']
-    Globals.getInstance().set_args(sys.argv)
-
-    assert Globals.getInstance().get_target_node() is None
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    patched_find_ports.assert_called()
-
-
-@pytest.mark.unit
-@patch('meshtastic.test.testAll', return_value=True)
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyFake1', '/dev/ttyFake2'])
-def test_main_test_two_ports_success(patched_find_ports, patched_test_all, reset_globals):
-    """Test --test two fake ports and testAll() is a simulated success"""
-    sys.argv = ['', '--test']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-    # TODO: why does this fail? patched_find_ports.assert_called()
-    patched_test_all.assert_called()
-
-
-@pytest.mark.unit
-@patch('meshtastic.test.testAll', return_value=False)
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyFake1', '/dev/ttyFake2'])
-def test_main_test_two_ports_fails(patched_find_ports, patched_test_all, reset_globals):
-    """Test --test two fake ports and testAll() is a simulated failure"""
-    sys.argv = ['', '--test']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    # TODO: why does this fail? patched_find_ports.assert_called()
-    patched_test_all.assert_called()
-
-
-@pytest.mark.unit
-def test_main_info(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_info_with_tcp_interface(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info', '--host', 'meshtastic.local']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=TCPInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.tcp_interface.TCPInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_info_with_ble_interface(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info', '--ble', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=BLEInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.ble_interface.BLEInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_no_proto(capsys, reset_globals):
-    """Test --noproto (using --info for output)"""
-    sys.argv = ['', '--info', '--noproto']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-
-    # Override the time.sleep so there is no loop
-    def my_sleep(amount):
-        sys.exit(0)
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface):
-        with patch('time.sleep', side_effect=my_sleep):
-            with pytest.raises(SystemExit) as pytest_wrapped_e:
-                main()
-            assert pytest_wrapped_e.type == SystemExit
-            assert pytest_wrapped_e.value.code == 0
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-            assert err == ''
-
-
-@pytest.mark.unit
-def test_main_info_with_seriallog_stdout(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info', '--seriallog', 'stdout']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_info_with_seriallog_output_txt(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info', '--seriallog', 'output.txt']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-    # do some cleanup
-    os.remove('output.txt')
-
-
-@pytest.mark.unit
-def test_main_qr(capsys, reset_globals):
-    """Test --qr"""
-    sys.argv = ['', '--qr']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    # TODO: could mock/check url
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Primary channel URL', out, re.MULTILINE)
-        # if a qr code is generated it will have lots of these
-        assert re.search(r'\[7m', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_nodes(capsys, reset_globals):
-    """Test --nodes"""
-    sys.argv = ['', '--nodes']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showNodes():
-        print('inside mocked showNodes')
-    iface.showNodes.side_effect = mock_showNodes
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showNodes', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_set_owner_to_bob(capsys, reset_globals):
-    """Test --set-owner bob"""
-    sys.argv = ['', '--set-owner', 'bob']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Setting device owner to bob', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_set_ham_to_KI123(capsys, reset_globals):
-    """Test --set-ham KI123"""
-    sys.argv = ['', '--set-ham', 'KI123']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_turnOffEncryptionOnPrimaryChannel():
-        print('inside mocked turnOffEncryptionOnPrimaryChannel')
-    def mock_setOwner(name, is_licensed):
-        print('inside mocked setOwner')
-    mocked_node.turnOffEncryptionOnPrimaryChannel.side_effect = mock_turnOffEncryptionOnPrimaryChannel
-    mocked_node.setOwner.side_effect = mock_setOwner
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Setting Ham ID to KI123', out, re.MULTILINE)
-        assert re.search(r'inside mocked setOwner', out, re.MULTILINE)
-        assert re.search(r'inside mocked turnOffEncryptionOnPrimaryChannel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_reboot(capsys, reset_globals):
-    """Test --reboot"""
-    sys.argv = ['', '--reboot']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_reboot():
-        print('inside mocked reboot')
-    mocked_node.reboot.side_effect = mock_reboot
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked reboot', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_sendtext(capsys, reset_globals):
-    """Test --sendtext"""
-    sys.argv = ['', '--sendtext', 'hello']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendText(text, dest, wantAck, channelIndex):
-        print('inside mocked sendText')
-    iface.sendText.side_effect = mock_sendText
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Sending text message', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendText', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_sendtext_with_channel(capsys, reset_globals):
-    """Test --sendtext"""
-    sys.argv = ['', '--sendtext', 'hello', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendText(text, dest, wantAck, channelIndex):
-        print('inside mocked sendText')
-    iface.sendText.side_effect = mock_sendText
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Sending text message', out, re.MULTILINE)
-        assert re.search(r'on channelIndex:1', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendText', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_sendtext_with_invalid_channel(capsys, reset_globals):
-    """Test --sendtext"""
-    sys.argv = ['', '--sendtext', 'hello', '--ch-index', '-1']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getChannelByChannelIndex.return_value = None
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        iface.getNode.return_value.getChannelByChannelIndex.return_value = None
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'is not a valid channel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_sendtext_with_invalid_channel_nine(capsys, reset_globals):
-    """Test --sendtext"""
-    sys.argv = ['', '--sendtext', 'hello', '--ch-index', '9']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        iface.getNode.return_value.getChannelByChannelIndex.return_value = None
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'is not a valid channel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_sendtext_with_dest(capsys, reset_globals):
-    """Test --sendtext with --dest"""
-    sys.argv = ['', '--sendtext', 'hello', '--dest', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendText(text, dest, wantAck, channelIndex):
-        print('inside mocked sendText')
-    iface.sendText.side_effect = mock_sendText
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Sending text message', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendText', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_sendping(capsys, reset_globals):
-    """Test --sendping"""
-    sys.argv = ['', '--sendping']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendData(payload, dest, portNum, wantAck, wantResponse):
-        print('inside mocked sendData')
-    iface.sendData.side_effect = mock_sendData
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Sending ping message', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendData', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_setlat(capsys, reset_globals):
-    """Test --sendlat"""
-    sys.argv = ['', '--setlat', '37.5']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_writeConfig():
-        print('inside mocked writeConfig')
-    mocked_node.writeConfig.side_effect = mock_writeConfig
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendPosition(lat, lon, alt):
-        print('inside mocked sendPosition')
-    iface.sendPosition.side_effect = mock_sendPosition
-    iface.localNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Fixing latitude', out, re.MULTILINE)
-        assert re.search(r'Setting device position', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendPosition', out, re.MULTILINE)
-        # TODO: Why does this not work? assert re.search(r'inside mocked writeConfig', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_setlon(capsys, reset_globals):
-    """Test --setlon"""
-    sys.argv = ['', '--setlon', '-122.1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_writeConfig():
-        print('inside mocked writeConfig')
-    mocked_node.writeConfig.side_effect = mock_writeConfig
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendPosition(lat, lon, alt):
-        print('inside mocked sendPosition')
-    iface.sendPosition.side_effect = mock_sendPosition
-    iface.localNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Fixing longitude', out, re.MULTILINE)
-        assert re.search(r'Setting device position', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendPosition', out, re.MULTILINE)
-        # TODO: Why does this not work? assert re.search(r'inside mocked writeConfig', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_setalt(capsys, reset_globals):
-    """Test --setalt"""
-    sys.argv = ['', '--setalt', '51']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_writeConfig():
-        print('inside mocked writeConfig')
-    mocked_node.writeConfig.side_effect = mock_writeConfig
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendPosition(lat, lon, alt):
-        print('inside mocked sendPosition')
-    iface.sendPosition.side_effect = mock_sendPosition
-    iface.localNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Fixing altitude', out, re.MULTILINE)
-        assert re.search(r'Setting device position', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendPosition', out, re.MULTILINE)
-        # TODO: Why does this not work? assert re.search(r'inside mocked writeConfig', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_set_team_valid(capsys, reset_globals):
-    """Test --set-team"""
-    sys.argv = ['', '--set-team', 'CYAN']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_setOwner(team):
-        print('inside mocked setOwner')
-    mocked_node.setOwner.side_effect = mock_setOwner
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.localNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with patch('meshtastic.mesh_pb2.Team') as mm:
-            mm.Name.return_value = 'FAKENAME'
-            mm.Value.return_value = 'FAKEVAL'
-            main()
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'Setting team to', out, re.MULTILINE)
-            assert err == ''
-            mo.assert_called()
-            mm.Name.assert_called()
-            mm.Value.assert_called()
-
-
-@pytest.mark.unit
-def test_main_set_team_invalid(capsys, reset_globals):
-    """Test --set-team using an invalid team name"""
-    sys.argv = ['', '--set-team', 'NOTCYAN']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-
-    def throw_an_exception(exc):
-        raise ValueError("Fake exception.")
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with patch('meshtastic.mesh_pb2.Team') as mm:
-            mm.Value.side_effect = throw_an_exception
-            main()
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'ERROR: Team', out, re.MULTILINE)
-            assert err == ''
-            mo.assert_called()
-            mm.Value.assert_called()
-
-
-@pytest.mark.unit
-def test_main_seturl(capsys, reset_globals):
-    """Test --seturl (url used below is what is generated after a factory_reset)"""
-    sys.argv = ['', '--seturl', 'https://www.meshtastic.org/d/#CgUYAyIBAQ']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_set_valid(capsys, reset_globals):
-    """Test --set with valid field"""
-    sys.argv = ['', '--set', 'wifi_ssid', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Set wifi_ssid to foo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_set_with_invalid(capsys, reset_globals):
-    """Test --set with invalid field"""
-    sys.argv = ['', '--set', 'foo', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_user_prefs = MagicMock()
-    mocked_user_prefs.DESCRIPTOR.fields_by_name.get.return_value = None
-
-    mocked_node = MagicMock(autospec=Node)
-    mocked_node.radioConfig.preferences = ( mocked_user_prefs )
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'does not have an attribute called foo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-# TODO: write some negative --configure tests
-@pytest.mark.unit
-def test_main_configure(capsys, reset_globals):
-    """Test --configure with valid file"""
-    sys.argv = ['', '--configure', 'example_config.yaml']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Setting device owner', out, re.MULTILINE)
-        assert re.search(r'Setting channel url', out, re.MULTILINE)
-        assert re.search(r'Fixing altitude', out, re.MULTILINE)
-        assert re.search(r'Fixing latitude', out, re.MULTILINE)
-        assert re.search(r'Fixing longitude', out, re.MULTILINE)
-        assert re.search(r'Writing modified preferences', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_add_valid(capsys, reset_globals):
-    """Test --ch-add with valid channel name, and that channel name does not already exist"""
-    sys.argv = ['', '--ch-add', 'testing']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_channel = MagicMock(autospec=Channel)
-    # TODO: figure out how to get it to print the channel name instead of MagicMock
-
-    mocked_node = MagicMock(autospec=Node)
-    # set it up so we do not already have a channel named this
-    mocked_node.getChannelByName.return_value = False
-    # set it up so we have free channels
-    mocked_node.getDisabledChannel.return_value = mocked_channel
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_add_invalid_name_too_long(capsys, reset_globals):
-    """Test --ch-add with invalid channel name, name too long"""
-    sys.argv = ['', '--ch-add', 'testingtestingtesting']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_channel = MagicMock(autospec=Channel)
-    # TODO: figure out how to get it to print the channel name instead of MagicMock
-
-    mocked_node = MagicMock(autospec=Node)
-    # set it up so we do not already have a channel named this
-    mocked_node.getChannelByName.return_value = False
-    # set it up so we have free channels
-    mocked_node.getDisabledChannel.return_value = mocked_channel
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Channel name must be shorter', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_add_but_name_already_exists(capsys, reset_globals):
-    """Test --ch-add with a channel name that already exists"""
-    sys.argv = ['', '--ch-add', 'testing']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    # set it up so we do not already have a channel named this
-    mocked_node.getChannelByName.return_value = True
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: This node already has', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_add_but_no_more_channels(capsys, reset_globals):
-    """Test --ch-add with but there are no more channels"""
-    sys.argv = ['', '--ch-add', 'testing']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    # set it up so we do not already have a channel named this
-    mocked_node.getChannelByName.return_value = False
-    # set it up so we have free channels
-    mocked_node.getDisabledChannel.return_value = None
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: No free channels were found', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_del(capsys, reset_globals):
-    """Test --ch-del with valid secondary channel to be deleted"""
-    sys.argv = ['', '--ch-del', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Deleting channel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_del_no_ch_index_specified(capsys, reset_globals):
-    """Test --ch-del without a valid ch-index"""
-    sys.argv = ['', '--ch-del']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_del_primary_channel(capsys, reset_globals):
-    """Test --ch-del on ch-index=0"""
-    sys.argv = ['', '--ch-del', '--ch-index', '0']
-    Globals.getInstance().set_args(sys.argv)
-    Globals.getInstance().set_channel_index(1)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Cannot delete primary channel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_enable_valid_secondary_channel(capsys, reset_globals):
-    """Test --ch-enable with --ch-index"""
-    sys.argv = ['', '--ch-enable', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Writing modified channels', out, re.MULTILINE)
-        assert err == ''
-        assert Globals.getInstance().get_channel_index() == 1
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_disable_valid_secondary_channel(capsys, reset_globals):
-    """Test --ch-disable with --ch-index"""
-    sys.argv = ['', '--ch-disable', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Writing modified channels', out, re.MULTILINE)
-        assert err == ''
-        assert Globals.getInstance().get_channel_index() == 1
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_enable_without_a_ch_index(capsys, reset_globals):
-    """Test --ch-enable without --ch-index"""
-    sys.argv = ['', '--ch-enable']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-        assert err == ''
-        assert Globals.getInstance().get_channel_index() is None
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_enable_primary_channel(capsys, reset_globals):
-    """Test --ch-enable with --ch-index = 0"""
-    sys.argv = ['', '--ch-enable', '--ch-index', '0']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Cannot enable/disable PRIMARY', out, re.MULTILINE)
-        assert err == ''
-        assert Globals.getInstance().get_channel_index() == 0
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_range_options(capsys, reset_globals):
-    """Test changing the various range options."""
-    range_options = ['--ch-longslow', '--ch-longfast', '--ch-mediumslow',
-                     '--ch-mediumfast', '--ch-shortslow', '--ch-shortfast']
-    for range_option in range_options:
-        sys.argv = ['', f"{range_option}" ]
-        Globals.getInstance().set_args(sys.argv)
-
-        mocked_node = MagicMock(autospec=Node)
-
-        iface = MagicMock(autospec=SerialInterface)
-        iface.getNode.return_value = mocked_node
-
-        with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-            main()
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'Writing modified channels', out, re.MULTILINE)
-            assert err == ''
-            mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_ch_longsfast_on_non_primary_channel(capsys, reset_globals):
-    """Test --ch-longfast --ch-index 1"""
-    sys.argv = ['', '--ch-longfast', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Standard channel settings', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-# PositionFlags:
-# Misc info that might be helpful (this info will grow stale, just
-# a snapshot of the values.) The radioconfig_pb2.PositionFlags.Name and bit values are:
-# POS_UNDEFINED 0
-# POS_ALTITUDE 1
-# POS_ALT_MSL 2
-# POS_GEO_SEP 4
-# POS_DOP 8
-# POS_HVDOP 16
-# POS_BATTERY 32
-# POS_SATINVIEW 64
-# POS_SEQ_NOS 128
-# POS_TIMESTAMP 256
-
-@pytest.mark.unit
-def test_main_pos_fields_no_args(capsys, reset_globals):
-    """Test --pos-fields no args (which shows settings)"""
-    sys.argv = ['', '--pos-fields']
-    Globals.getInstance().set_args(sys.argv)
-
-    pos_flags = MagicMock(autospec=meshtastic.radioconfig_pb2.PositionFlags)
-
-    with patch('meshtastic.serial_interface.SerialInterface') as mo:
-        with patch('meshtastic.radioconfig_pb2.PositionFlags', return_value=pos_flags) as mrc:
-            # kind of cheating here, we are setting up the node
-            mocked_node = MagicMock(autospec=Node)
-            anode = mocked_node()
-            anode.radioConfig.preferences.position_flags = 35
-            Globals.getInstance().set_target_node(anode)
-
-            mrc.values.return_value = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256]
-            # Note: When you use side_effect and a list, each call will use a value from the front of the list then
-            # remove that value from the list. If there are three values in the list, we expect it to be called
-            # three times.
-            mrc.Name.side_effect = [ 'POS_ALTITUDE', 'POS_ALT_MSL', 'POS_BATTERY' ]
-
-            main()
-
-            mrc.Name.assert_called()
-            mrc.values.assert_called()
-            mo.assert_called()
-
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'POS_ALTITUDE POS_ALT_MSL POS_BATTERY', out, re.MULTILINE)
-            assert err == ''
-
-
-@pytest.mark.unit
-def test_main_pos_fields_arg_of_zero(capsys, reset_globals):
-    """Test --pos-fields an arg of 0 (which shows list)"""
-    sys.argv = ['', '--pos-fields', '0']
-    Globals.getInstance().set_args(sys.argv)
-
-    pos_flags = MagicMock(autospec=meshtastic.radioconfig_pb2.PositionFlags)
-
-    with patch('meshtastic.serial_interface.SerialInterface') as mo:
-        with patch('meshtastic.radioconfig_pb2.PositionFlags', return_value=pos_flags) as mrc:
-
-            def throw_value_error_exception(exc):
-                raise ValueError()
-            mrc.Value.side_effect = throw_value_error_exception
-            mrc.keys.return_value = [ 'POS_UNDEFINED', 'POS_ALTITUDE', 'POS_ALT_MSL',
-                                      'POS_GEO_SEP', 'POS_DOP', 'POS_HVDOP', 'POS_BATTERY',
-                                      'POS_SATINVIEW', 'POS_SEQ_NOS', 'POS_TIMESTAMP']
-
-            main()
-
-            mrc.Value.assert_called()
-            mrc.keys.assert_called()
-            mo.assert_called()
-
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'ERROR: supported position fields are:', out, re.MULTILINE)
-            assert re.search(r"['POS_UNDEFINED', 'POS_ALTITUDE', 'POS_ALT_MSL', 'POS_GEO_SEP',"\
-                              "'POS_DOP', 'POS_HVDOP', 'POS_BATTERY', 'POS_SATINVIEW', 'POS_SEQ_NOS',"\
-                              "'POS_TIMESTAMP']", out, re.MULTILINE)
-            assert err == ''
-
-
-@pytest.mark.unit
-def test_main_pos_fields_valid_values(capsys, reset_globals):
-    """Test --pos-fields with valid values"""
-    sys.argv = ['', '--pos-fields', 'POS_GEO_SEP', 'POS_ALT_MSL']
-    Globals.getInstance().set_args(sys.argv)
-
-    pos_flags = MagicMock(autospec=meshtastic.radioconfig_pb2.PositionFlags)
-
-    with patch('meshtastic.serial_interface.SerialInterface') as mo:
-        with patch('meshtastic.radioconfig_pb2.PositionFlags', return_value=pos_flags) as mrc:
-
-            mrc.Value.side_effect = [ 4, 2 ]
-
-            main()
-
-            mrc.Value.assert_called()
-            mo.assert_called()
-
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'Setting position fields to 6', out, re.MULTILINE)
-            assert re.search(r'Set position_flags to 6', out, re.MULTILINE)
-            assert re.search(r'Writing modified preferences to device', out, re.MULTILINE)
-            assert err == ''
-
-
-@pytest.mark.unit
-def test_main_get_with_valid_values(capsys, reset_globals):
-    """Test --get with valid values (with string, number, boolean)"""
-    sys.argv = ['', '--get', 'ls_secs', '--get', 'wifi_ssid', '--get', 'fixed_position']
-    Globals.getInstance().set_args(sys.argv)
-
-    with patch('meshtastic.serial_interface.SerialInterface') as mo:
-
-        # kind of cheating here, we are setting up the node
-        mocked_node = MagicMock(autospec=Node)
-        anode = mocked_node()
-        anode.radioConfig.preferences.wifi_ssid = 'foo'
-        anode.radioConfig.preferences.ls_secs = 300
-        anode.radioConfig.preferences.fixed_position = False
-        Globals.getInstance().set_target_node(anode)
-
-        main()
-
-        mo.assert_called()
-
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'ls_secs: 300', out, re.MULTILINE)
-        assert re.search(r'wifi_ssid: foo', out, re.MULTILINE)
-        assert re.search(r'fixed_position: False', out, re.MULTILINE)
-        assert err == ''
-
-
-@pytest.mark.unit
-def test_main_get_with_invalid(capsys, reset_globals):
-    """Test --get with invalid field"""
-    sys.argv = ['', '--get', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_user_prefs = MagicMock()
-    mocked_user_prefs.DESCRIPTOR.fields_by_name.get.return_value = None
-
-    mocked_node = MagicMock(autospec=Node)
-    mocked_node.radioConfig.preferences = ( mocked_user_prefs )
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'does not have an attribute called foo', out, re.MULTILINE)
-        assert re.search(r'Choices in sorted order are', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_setchan(capsys, reset_globals):
-    """Test --setchan (deprecated)"""
-    sys.argv = ['', '--setchan', 'a', 'b']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface):
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-
-
-@pytest.mark.unit
-def test_main_onReceive_empty(caplog, reset_globals):
-    """Test onReceive"""
-    sys.argv = ['']
-    Globals.getInstance().set_args(sys.argv)
-    iface = MagicMock(autospec=SerialInterface)
-    packet = {'decoded': 'foo'}
-    with caplog.at_level(logging.DEBUG):
-        onReceive(packet, iface)
-    assert re.search(r'in onReceive', caplog.text, re.MULTILINE)
-
-
-#    TODO: use this captured position app message (might want/need in the future)
-#    packet = {
-#            'to': 4294967295,
-#            'decoded': {
-#                'portnum': 'POSITION_APP',
-#                'payload': "M69\306a"
-#                },
-#            'id': 334776976,
-#            'hop_limit': 3
-#            }
-
-@pytest.mark.unit
-def test_main_onReceive_with_sendtext(caplog, reset_globals):
-    """Test onReceive with sendtext
-       The entire point of this test is to make sure the interface.close() call
-       is made in onReceive().
-    """
-    sys.argv = ['', '--sendtext', 'hello']
-    Globals.getInstance().set_args(sys.argv)
-
-    # Note: 'TEXT_MESSAGE_APP' value is 1
-    packet = {
-            'to': 4294967295,
-            'decoded': {
-                'portnum': 1,
-                'payload': "hello"
-                },
-            'id': 334776977,
-            'hop_limit': 3,
-            'want_ack': True
-            }
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.myInfo.my_node_num = 4294967295
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with caplog.at_level(logging.DEBUG):
-            main()
-            onReceive(packet, iface)
-        assert re.search(r'in onReceive', caplog.text, re.MULTILINE)
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_onReceive_with_reply(caplog, capsys, reset_globals):
-    """Test onReceive with a reply
-       To capture: on one device run '--sendtext aaa --reply' and on another
-       device run '--sendtext bbb --reply', then back to the first device and
-       run '--sendtext aaa2 --reply'. You should now see a "Sending reply" message.
-    """
-    sys.argv = ['', '--sendtext', 'hello', '--reply']
-    Globals.getInstance().set_args(sys.argv)
-
-    # Note: 'TEXT_MESSAGE_APP' value is 1
-
-    send_packet = {
-            'to': 4294967295,
-            'decoded': {
-                'portnum': 1,
-                'payload': "hello"
-                },
-            'id': 334776977,
-            'hop_limit': 3,
-            'want_ack': True
-            }
-
-    reply_packet = {
-            'from': 682968668,
-            'to': 4294967295,
-            'decoded': {
-                'portnum': 'TEXT_MESSAGE_APP',
-                'payload': b'bbb',
-                'text': 'bbb'
-                },
-            'id': 1709936182,
-            'rxTime': 1640381999,
-            'rxSnr': 6.0,
-            'hopLimit': 3,
-            'raw': 'faked',
-            'fromId': '!28b5465c',
-            'toId': '^all'
-            }
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.myInfo.my_node_num = 4294967295
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with caplog.at_level(logging.DEBUG):
-            main()
-            onReceive(send_packet, iface)
-            onReceive(reply_packet, iface)
-        assert re.search(r'in onReceive', caplog.text, re.MULTILINE)
-        out, err = capsys.readouterr()
-        assert re.search(r'got msg ', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_onConnection(reset_globals, capsys):
-    """Test onConnection"""
-    sys.argv = ['']
-    Globals.getInstance().set_args(sys.argv)
-    iface = MagicMock(autospec=SerialInterface)
-    class TempTopic:
-        """ temp class for topic """
-        def getName(self):
-            """ return the fake name of a topic"""
-            return 'foo'
-    mytopic = TempTopic()
-    onConnection(iface, mytopic)
-    out, err = capsys.readouterr()
-    assert re.search(r'Connection changed: foo', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_main_export_config(reset_globals, capsys):
-    """Test export_config() function directly"""
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.getLongName.return_value = 'foo'
-        mo.localNode.getURL.return_value = 'bar'
-        mo.getMyNodeInfo().get.return_value = { 'latitudeI': 1100000000, 'longitudeI': 1200000000,
-                                                'altitude': 100, 'batteryLevel': 34, 'latitude': 110.0,
-                                                'longitude': 120.0}
-        mo.localNode.radioConfig.preferences = """phone_timeout_secs: 900
-ls_secs: 300
-position_broadcast_smart: true
-fixed_position: true
-position_flags: 35"""
-        export_config(mo)
-    out, err = capsys.readouterr()
-    assert re.search(r'owner: foo', out, re.MULTILINE)
-    assert re.search(r'channel_url: bar', out, re.MULTILINE)
-    assert re.search(r'location:', out, re.MULTILINE)
-    assert re.search(r'lat: 110.0', out, re.MULTILINE)
-    assert re.search(r'lon: 120.0', out, re.MULTILINE)
-    assert re.search(r'alt: 100', out, re.MULTILINE)
-    assert re.search(r'user_prefs:', out, re.MULTILINE)
-    assert re.search(r'phone_timeout_secs: 900', out, re.MULTILINE)
-    assert re.search(r'ls_secs: 300', out, re.MULTILINE)
-    assert re.search(r"position_broadcast_smart: 'true'", out, re.MULTILINE)
-    assert re.search(r"fixed_position: 'true'", out, re.MULTILINE)
-    assert re.search(r"position_flags: 35", out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_main_export_config_called_from_main(capsys, reset_globals):
-    """Test --export-config"""
-    sys.argv = ['', '--export-config']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'# start of Meshtastic configure yaml', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-@pytest.mark.unit
-def test_main_gpio_rd_no_gpio_channel(capsys, reset_globals):
-    """Test --gpio_rd with no named gpio channel"""
-    sys.argv = ['', '--gpio-rd', '0x10']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.localNode.getChannelByName.return_value = None
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface):
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        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_main_gpio_rd_no_dest(capsys, reset_globals):
-    """Test --gpio_rd with a named gpio channel but no dest was specified"""
-    sys.argv = ['', '--gpio-rd', '0x2000']
-    Globals.getInstance().set_args(sys.argv)
-
-    channel = Channel(index=1, role=1)
-    channel.settings.modem_config = 3
-    channel.settings.psk = b'\x01'
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.localNode.getChannelByName.return_value = channel
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface):
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Warning: Must use a destination node ID', out)
-        assert err == ''
-
-
-@pytest.mark.unit
-def test_main_gpio_rd(caplog, capsys, reset_globals):
-    """Test --gpio_rd with a named gpio channel"""
-    # Note: On the Heltec v2.1, there is a GPIO pin GPIO 13 that does not have a
-    # red arrow (meaning ok to use for our purposes)
-    # See https://resource.heltec.cn/download/WiFi_LoRa_32/WIFI_LoRa_32_V2.pdf
-    # To find out the mask for GPIO 13, let us assign n as 13.
-    # 1. Subtract 1 from n (n is now 12)
-    # 2. Find the 2^n or 2^12 (4096)
-    # 3. Convert 4096 decimal to hex (0x1000)
-    # You can use python:
-    # >>> print(hex(2**12))
-    # 0x1000
-    sys.argv = ['', '--gpio-rd', '0x1000', '--dest', '!1234']
-    Globals.getInstance().set_args(sys.argv)
-
-    channel = Channel(index=1, role=1)
-    channel.settings.modem_config = 3
-    channel.settings.psk = b'\x01'
-
-    packet = {
-
-            'from': 682968668,
-            'to': 682968612,
-            'channel': 1,
-            'decoded': {
-                'portnum': 'REMOTE_HARDWARE_APP',
-                'payload': b'\x08\x05\x18\x80 ',
-                'requestId': 1629980484,
-                'remotehw': {
-                    'typ': 'READ_GPIOS_REPLY',
-                    'gpioValue': '4096',
-                    'raw': 'faked',
-                    'id': 1693085229,
-                    'rxTime': 1640294262,
-                    'rxSnr': 4.75,
-                    'hopLimit': 3,
-                    'wantAck': True,
-                    }
-                }
-            }
-
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.localNode.getChannelByName.return_value = channel
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with caplog.at_level(logging.DEBUG):
-            main()
-            onGPIOreceive(packet, mo)
-    assert re.search(r'readGPIOs nodeid:!1234 mask:4096', caplog.text, re.MULTILINE)
-    out, err = capsys.readouterr()
-    assert re.search(r'Connected to radio', out, re.MULTILINE)
-    assert re.search(r'Reading GPIO mask 0x1000 ', out, re.MULTILINE)
-    assert re.search(r'Received RemoteHardware typ=READ_GPIOS_REPLY, gpio_value=4096', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_main_getPref_valid_field(capsys, reset_globals):
-    """Test getPref() with a valid field"""
-    prefs = MagicMock()
-    prefs.DESCRIPTOR.fields_by_name.get.return_value = 'ls_secs'
-    prefs.wifi_ssid = 'foo'
-    prefs.ls_secs = 300
-    prefs.fixed_position = False
-
-    getPref(prefs, 'ls_secs')
-    out, err = capsys.readouterr()
-    assert re.search(r'ls_secs: 300', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_main_getPref_invalid_field(capsys, reset_globals):
-    """Test getPref() with an invalid field"""
-
-    class Field:
-        """Simple class for testing."""
-
-        def __init__(self, name):
-            """constructor"""
-            self.name = name
-
-    prefs = MagicMock()
-    prefs.DESCRIPTOR.fields_by_name.get.return_value = None
-
-    # Note: This is a subset of the real fields
-    ls_secs_field = Field('ls_secs')
-    is_router = Field('is_router')
-    fixed_position = Field('fixed_position')
-
-    fields = [ ls_secs_field, is_router, fixed_position ]
-    prefs.DESCRIPTOR.fields = fields
-
-    getPref(prefs, 'foo')
-
-    out, err = capsys.readouterr()
-    assert re.search(r'does not have an attribute called foo', out, re.MULTILINE)
-    # ensure they are sorted
-    assert re.search(r'fixed_position\s+is_router\s+ls_secs', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_main_setPref_valid_field(capsys, reset_globals):
-    """Test setPref() with a valid field"""
-
-    class Field:
-        """Simple class for testing."""
-
-        def __init__(self, name, enum_type):
-            """constructor"""
-            self.name = name
-            self.enum_type = enum_type
-
-    ls_secs_field = Field('ls_secs', 'int')
-    prefs = MagicMock()
-    prefs.DESCRIPTOR.fields_by_name.get.return_value = ls_secs_field
-
-    setPref(prefs, 'ls_secs', '300')
-    out, err = capsys.readouterr()
-    assert re.search(r'Set ls_secs to 300', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_main_setPref_invalid_field(capsys, reset_globals):
-    """Test setPref() with a invalid field"""
-
-
-    class Field:
-        """Simple class for testing."""
-
-        def __init__(self, name):
-            """constructor"""
-            self.name = name
-
-    prefs = MagicMock()
-    prefs.DESCRIPTOR.fields_by_name.get.return_value = None
-
-    # Note: This is a subset of the real fields
-    ls_secs_field = Field('ls_secs')
-    is_router = Field('is_router')
-    fixed_position = Field('fixed_position')
-
-    fields = [ ls_secs_field, is_router, fixed_position ]
-    prefs.DESCRIPTOR.fields = fields
-
-    setPref(prefs, 'foo', '300')
-    out, err = capsys.readouterr()
-    assert re.search(r'does not have an attribute called foo', out, re.MULTILINE)
-    # ensure they are sorted
-    assert re.search(r'fixed_position\s+is_router\s+ls_secs', out, re.MULTILINE)
-    assert err == ''
-
-
-
-
-
-
-
-

Functions

-
-
-def test_main_ch_add_but_name_already_exists(capsys, reset_globals) -
-
-

Test –ch-add with a channel name that already exists

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_add_but_name_already_exists(capsys, reset_globals):
-    """Test --ch-add with a channel name that already exists"""
-    sys.argv = ['', '--ch-add', 'testing']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    # set it up so we do not already have a channel named this
-    mocked_node.getChannelByName.return_value = True
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: This node already has', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_ch_add_but_no_more_channels(capsys, reset_globals) -
-
-

Test –ch-add with but there are no more channels

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_add_but_no_more_channels(capsys, reset_globals):
-    """Test --ch-add with but there are no more channels"""
-    sys.argv = ['', '--ch-add', 'testing']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    # set it up so we do not already have a channel named this
-    mocked_node.getChannelByName.return_value = False
-    # set it up so we have free channels
-    mocked_node.getDisabledChannel.return_value = None
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: No free channels were found', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_ch_add_invalid_name_too_long(capsys, reset_globals) -
-
-

Test –ch-add with invalid channel name, name too long

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_add_invalid_name_too_long(capsys, reset_globals):
-    """Test --ch-add with invalid channel name, name too long"""
-    sys.argv = ['', '--ch-add', 'testingtestingtesting']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_channel = MagicMock(autospec=Channel)
-    # TODO: figure out how to get it to print the channel name instead of MagicMock
-
-    mocked_node = MagicMock(autospec=Node)
-    # set it up so we do not already have a channel named this
-    mocked_node.getChannelByName.return_value = False
-    # set it up so we have free channels
-    mocked_node.getDisabledChannel.return_value = mocked_channel
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Channel name must be shorter', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_ch_add_valid(capsys, reset_globals) -
-
-

Test –ch-add with valid channel name, and that channel name does not already exist

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_add_valid(capsys, reset_globals):
-    """Test --ch-add with valid channel name, and that channel name does not already exist"""
-    sys.argv = ['', '--ch-add', 'testing']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_channel = MagicMock(autospec=Channel)
-    # TODO: figure out how to get it to print the channel name instead of MagicMock
-
-    mocked_node = MagicMock(autospec=Node)
-    # set it up so we do not already have a channel named this
-    mocked_node.getChannelByName.return_value = False
-    # set it up so we have free channels
-    mocked_node.getDisabledChannel.return_value = mocked_channel
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_ch_del(capsys, reset_globals) -
-
-

Test –ch-del with valid secondary channel to be deleted

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_del(capsys, reset_globals):
-    """Test --ch-del with valid secondary channel to be deleted"""
-    sys.argv = ['', '--ch-del', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Deleting channel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_ch_del_no_ch_index_specified(capsys, reset_globals) -
-
-

Test –ch-del without a valid ch-index

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_del_no_ch_index_specified(capsys, reset_globals):
-    """Test --ch-del without a valid ch-index"""
-    sys.argv = ['', '--ch-del']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_ch_del_primary_channel(capsys, reset_globals) -
-
-

Test –ch-del on ch-index=0

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_del_primary_channel(capsys, reset_globals):
-    """Test --ch-del on ch-index=0"""
-    sys.argv = ['', '--ch-del', '--ch-index', '0']
-    Globals.getInstance().set_args(sys.argv)
-    Globals.getInstance().set_channel_index(1)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Cannot delete primary channel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_ch_disable_valid_secondary_channel(capsys, reset_globals) -
-
-

Test –ch-disable with –ch-index

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_disable_valid_secondary_channel(capsys, reset_globals):
-    """Test --ch-disable with --ch-index"""
-    sys.argv = ['', '--ch-disable', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Writing modified channels', out, re.MULTILINE)
-        assert err == ''
-        assert Globals.getInstance().get_channel_index() == 1
-        mo.assert_called()
-
-
-
-def test_main_ch_enable_primary_channel(capsys, reset_globals) -
-
-

Test –ch-enable with –ch-index = 0

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_enable_primary_channel(capsys, reset_globals):
-    """Test --ch-enable with --ch-index = 0"""
-    sys.argv = ['', '--ch-enable', '--ch-index', '0']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Cannot enable/disable PRIMARY', out, re.MULTILINE)
-        assert err == ''
-        assert Globals.getInstance().get_channel_index() == 0
-        mo.assert_called()
-
-
-
-def test_main_ch_enable_valid_secondary_channel(capsys, reset_globals) -
-
-

Test –ch-enable with –ch-index

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_enable_valid_secondary_channel(capsys, reset_globals):
-    """Test --ch-enable with --ch-index"""
-    sys.argv = ['', '--ch-enable', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Writing modified channels', out, re.MULTILINE)
-        assert err == ''
-        assert Globals.getInstance().get_channel_index() == 1
-        mo.assert_called()
-
-
-
-def test_main_ch_enable_without_a_ch_index(capsys, reset_globals) -
-
-

Test –ch-enable without –ch-index

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_enable_without_a_ch_index(capsys, reset_globals):
-    """Test --ch-enable without --ch-index"""
-    sys.argv = ['', '--ch-enable']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-        assert err == ''
-        assert Globals.getInstance().get_channel_index() is None
-        mo.assert_called()
-
-
-
-def test_main_ch_index_no_devices(patched_find_ports, capsys, reset_globals) -
-
-

Test –ch-index 1

-
- -Expand source code - -
@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=[])
-def test_main_ch_index_no_devices(patched_find_ports, capsys, reset_globals):
-    """Test --ch-index 1"""
-    sys.argv = ['', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert Globals.getInstance().get_channel_index() == 1
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: No Meshtastic devices detected', out, re.MULTILINE)
-    assert err == ''
-    patched_find_ports.assert_called()
-
-
-
-def test_main_ch_longsfast_on_non_primary_channel(capsys, reset_globals) -
-
-

Test –ch-longfast –ch-index 1

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_longsfast_on_non_primary_channel(capsys, reset_globals):
-    """Test --ch-longfast --ch-index 1"""
-    sys.argv = ['', '--ch-longfast', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Warning: Standard channel settings', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_ch_range_options(capsys, reset_globals) -
-
-

Test changing the various range options.

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_ch_range_options(capsys, reset_globals):
-    """Test changing the various range options."""
-    range_options = ['--ch-longslow', '--ch-longfast', '--ch-mediumslow',
-                     '--ch-mediumfast', '--ch-shortslow', '--ch-shortfast']
-    for range_option in range_options:
-        sys.argv = ['', f"{range_option}" ]
-        Globals.getInstance().set_args(sys.argv)
-
-        mocked_node = MagicMock(autospec=Node)
-
-        iface = MagicMock(autospec=SerialInterface)
-        iface.getNode.return_value = mocked_node
-
-        with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-            main()
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'Writing modified channels', out, re.MULTILINE)
-            assert err == ''
-            mo.assert_called()
-
-
-
-def test_main_configure(capsys, reset_globals) -
-
-

Test –configure with valid file

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_configure(capsys, reset_globals):
-    """Test --configure with valid file"""
-    sys.argv = ['', '--configure', 'example_config.yaml']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Setting device owner', out, re.MULTILINE)
-        assert re.search(r'Setting channel url', out, re.MULTILINE)
-        assert re.search(r'Fixing altitude', out, re.MULTILINE)
-        assert re.search(r'Fixing latitude', out, re.MULTILINE)
-        assert re.search(r'Fixing longitude', out, re.MULTILINE)
-        assert re.search(r'Writing modified preferences', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_export_config(reset_globals, capsys) -
-
-

Test export_config() function directly

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_export_config(reset_globals, capsys):
-    """Test export_config() function directly"""
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.getLongName.return_value = 'foo'
-        mo.localNode.getURL.return_value = 'bar'
-        mo.getMyNodeInfo().get.return_value = { 'latitudeI': 1100000000, 'longitudeI': 1200000000,
-                                                'altitude': 100, 'batteryLevel': 34, 'latitude': 110.0,
-                                                'longitude': 120.0}
-        mo.localNode.radioConfig.preferences = """phone_timeout_secs: 900
-ls_secs: 300
-position_broadcast_smart: true
-fixed_position: true
-position_flags: 35"""
-        export_config(mo)
-    out, err = capsys.readouterr()
-    assert re.search(r'owner: foo', out, re.MULTILINE)
-    assert re.search(r'channel_url: bar', out, re.MULTILINE)
-    assert re.search(r'location:', out, re.MULTILINE)
-    assert re.search(r'lat: 110.0', out, re.MULTILINE)
-    assert re.search(r'lon: 120.0', out, re.MULTILINE)
-    assert re.search(r'alt: 100', out, re.MULTILINE)
-    assert re.search(r'user_prefs:', out, re.MULTILINE)
-    assert re.search(r'phone_timeout_secs: 900', out, re.MULTILINE)
-    assert re.search(r'ls_secs: 300', out, re.MULTILINE)
-    assert re.search(r"position_broadcast_smart: 'true'", out, re.MULTILINE)
-    assert re.search(r"fixed_position: 'true'", out, re.MULTILINE)
-    assert re.search(r"position_flags: 35", out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_main_export_config_called_from_main(capsys, reset_globals) -
-
-

Test –export-config

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_export_config_called_from_main(capsys, reset_globals):
-    """Test --export-config"""
-    sys.argv = ['', '--export-config']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'# start of Meshtastic configure yaml', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_getPref_invalid_field(capsys, reset_globals) -
-
-

Test getPref() with an invalid field

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_getPref_invalid_field(capsys, reset_globals):
-    """Test getPref() with an invalid field"""
-
-    class Field:
-        """Simple class for testing."""
-
-        def __init__(self, name):
-            """constructor"""
-            self.name = name
-
-    prefs = MagicMock()
-    prefs.DESCRIPTOR.fields_by_name.get.return_value = None
-
-    # Note: This is a subset of the real fields
-    ls_secs_field = Field('ls_secs')
-    is_router = Field('is_router')
-    fixed_position = Field('fixed_position')
-
-    fields = [ ls_secs_field, is_router, fixed_position ]
-    prefs.DESCRIPTOR.fields = fields
-
-    getPref(prefs, 'foo')
-
-    out, err = capsys.readouterr()
-    assert re.search(r'does not have an attribute called foo', out, re.MULTILINE)
-    # ensure they are sorted
-    assert re.search(r'fixed_position\s+is_router\s+ls_secs', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_main_getPref_valid_field(capsys, reset_globals) -
-
-

Test getPref() with a valid field

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_getPref_valid_field(capsys, reset_globals):
-    """Test getPref() with a valid field"""
-    prefs = MagicMock()
-    prefs.DESCRIPTOR.fields_by_name.get.return_value = 'ls_secs'
-    prefs.wifi_ssid = 'foo'
-    prefs.ls_secs = 300
-    prefs.fixed_position = False
-
-    getPref(prefs, 'ls_secs')
-    out, err = capsys.readouterr()
-    assert re.search(r'ls_secs: 300', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_main_get_with_invalid(capsys, reset_globals) -
-
-

Test –get with invalid field

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_get_with_invalid(capsys, reset_globals):
-    """Test --get with invalid field"""
-    sys.argv = ['', '--get', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_user_prefs = MagicMock()
-    mocked_user_prefs.DESCRIPTOR.fields_by_name.get.return_value = None
-
-    mocked_node = MagicMock(autospec=Node)
-    mocked_node.radioConfig.preferences = ( mocked_user_prefs )
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'does not have an attribute called foo', out, re.MULTILINE)
-        assert re.search(r'Choices in sorted order are', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_get_with_valid_values(capsys, reset_globals) -
-
-

Test –get with valid values (with string, number, boolean)

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_get_with_valid_values(capsys, reset_globals):
-    """Test --get with valid values (with string, number, boolean)"""
-    sys.argv = ['', '--get', 'ls_secs', '--get', 'wifi_ssid', '--get', 'fixed_position']
-    Globals.getInstance().set_args(sys.argv)
-
-    with patch('meshtastic.serial_interface.SerialInterface') as mo:
-
-        # kind of cheating here, we are setting up the node
-        mocked_node = MagicMock(autospec=Node)
-        anode = mocked_node()
-        anode.radioConfig.preferences.wifi_ssid = 'foo'
-        anode.radioConfig.preferences.ls_secs = 300
-        anode.radioConfig.preferences.fixed_position = False
-        Globals.getInstance().set_target_node(anode)
-
-        main()
-
-        mo.assert_called()
-
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'ls_secs: 300', out, re.MULTILINE)
-        assert re.search(r'wifi_ssid: foo', out, re.MULTILINE)
-        assert re.search(r'fixed_position: False', out, re.MULTILINE)
-        assert err == ''
-
-
-
-def test_main_gpio_rd(caplog, capsys, reset_globals) -
-
-

Test –gpio_rd with a named gpio channel

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_gpio_rd(caplog, capsys, reset_globals):
-    """Test --gpio_rd with a named gpio channel"""
-    # Note: On the Heltec v2.1, there is a GPIO pin GPIO 13 that does not have a
-    # red arrow (meaning ok to use for our purposes)
-    # See https://resource.heltec.cn/download/WiFi_LoRa_32/WIFI_LoRa_32_V2.pdf
-    # To find out the mask for GPIO 13, let us assign n as 13.
-    # 1. Subtract 1 from n (n is now 12)
-    # 2. Find the 2^n or 2^12 (4096)
-    # 3. Convert 4096 decimal to hex (0x1000)
-    # You can use python:
-    # >>> print(hex(2**12))
-    # 0x1000
-    sys.argv = ['', '--gpio-rd', '0x1000', '--dest', '!1234']
-    Globals.getInstance().set_args(sys.argv)
-
-    channel = Channel(index=1, role=1)
-    channel.settings.modem_config = 3
-    channel.settings.psk = b'\x01'
-
-    packet = {
-
-            'from': 682968668,
-            'to': 682968612,
-            'channel': 1,
-            'decoded': {
-                'portnum': 'REMOTE_HARDWARE_APP',
-                'payload': b'\x08\x05\x18\x80 ',
-                'requestId': 1629980484,
-                'remotehw': {
-                    'typ': 'READ_GPIOS_REPLY',
-                    'gpioValue': '4096',
-                    'raw': 'faked',
-                    'id': 1693085229,
-                    'rxTime': 1640294262,
-                    'rxSnr': 4.75,
-                    'hopLimit': 3,
-                    'wantAck': True,
-                    }
-                }
-            }
-
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.localNode.getChannelByName.return_value = channel
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with caplog.at_level(logging.DEBUG):
-            main()
-            onGPIOreceive(packet, mo)
-    assert re.search(r'readGPIOs nodeid:!1234 mask:4096', caplog.text, re.MULTILINE)
-    out, err = capsys.readouterr()
-    assert re.search(r'Connected to radio', out, re.MULTILINE)
-    assert re.search(r'Reading GPIO mask 0x1000 ', out, re.MULTILINE)
-    assert re.search(r'Received RemoteHardware typ=READ_GPIOS_REPLY, gpio_value=4096', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_main_gpio_rd_no_dest(capsys, reset_globals) -
-
-

Test –gpio_rd with a named gpio channel but no dest was specified

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_gpio_rd_no_dest(capsys, reset_globals):
-    """Test --gpio_rd with a named gpio channel but no dest was specified"""
-    sys.argv = ['', '--gpio-rd', '0x2000']
-    Globals.getInstance().set_args(sys.argv)
-
-    channel = Channel(index=1, role=1)
-    channel.settings.modem_config = 3
-    channel.settings.psk = b'\x01'
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.localNode.getChannelByName.return_value = channel
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface):
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'Warning: Must use a destination node ID', out)
-        assert err == ''
-
-
-
-def test_main_gpio_rd_no_gpio_channel(capsys, reset_globals) -
-
-

Test –gpio_rd with no named gpio channel

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_gpio_rd_no_gpio_channel(capsys, reset_globals):
-    """Test --gpio_rd with no named gpio channel"""
-    sys.argv = ['', '--gpio-rd', '0x10']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.localNode.getChannelByName.return_value = None
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface):
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        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 == ''
-
-
-
-def test_main_info(capsys, reset_globals) -
-
-

Test –info

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_info(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_info_with_ble_interface(capsys, reset_globals) -
-
-

Test –info

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_info_with_ble_interface(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info', '--ble', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=BLEInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.ble_interface.BLEInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_info_with_seriallog_output_txt(capsys, reset_globals) -
-
-

Test –info

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_info_with_seriallog_output_txt(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info', '--seriallog', 'output.txt']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-    # do some cleanup
-    os.remove('output.txt')
-
-
-
-def test_main_info_with_seriallog_stdout(capsys, reset_globals) -
-
-

Test –info

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_info_with_seriallog_stdout(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info', '--seriallog', 'stdout']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_info_with_tcp_interface(capsys, reset_globals) -
-
-

Test –info

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_info_with_tcp_interface(capsys, reset_globals):
-    """Test --info"""
-    sys.argv = ['', '--info', '--host', 'meshtastic.local']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=TCPInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-    with patch('meshtastic.tcp_interface.TCPInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_init_parser_no_args(capsys, reset_globals) -
-
-

Test no arguments

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_init_parser_no_args(capsys, reset_globals):
-    """Test no arguments"""
-    sys.argv = ['']
-    Globals.getInstance().set_args(sys.argv)
-    initParser()
-    out, err = capsys.readouterr()
-    assert out == ''
-    assert err == ''
-
-
-
-def test_main_init_parser_version(capsys, reset_globals) -
-
-

Test –version

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_init_parser_version(capsys, reset_globals):
-    """Test --version"""
-    sys.argv = ['', '--version']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        initParser()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-    out, err = capsys.readouterr()
-    assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
-    assert err == ''
-
-
-
-def test_main_main_no_args(reset_globals) -
-
-

Test with no args

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_main_no_args(reset_globals):
-    """Test with no args"""
-    sys.argv = ['']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-
-def test_main_main_version(capsys, reset_globals) -
-
-

Test –version

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_main_version(capsys, reset_globals):
-    """Test --version"""
-    sys.argv = ['', '--version']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-    out, err = capsys.readouterr()
-    assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
-    assert err == ''
-
-
-
-def test_main_no_proto(capsys, reset_globals) -
-
-

Test –noproto (using –info for output)

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_no_proto(capsys, reset_globals):
-    """Test --noproto (using --info for output)"""
-    sys.argv = ['', '--info', '--noproto']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showInfo():
-        print('inside mocked showInfo')
-    iface.showInfo.side_effect = mock_showInfo
-
-    # Override the time.sleep so there is no loop
-    def my_sleep(amount):
-        sys.exit(0)
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface):
-        with patch('time.sleep', side_effect=my_sleep):
-            with pytest.raises(SystemExit) as pytest_wrapped_e:
-                main()
-            assert pytest_wrapped_e.type == SystemExit
-            assert pytest_wrapped_e.value.code == 0
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'inside mocked showInfo', out, re.MULTILINE)
-            assert err == ''
-
-
-
-def test_main_nodes(capsys, reset_globals) -
-
-

Test –nodes

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_nodes(capsys, reset_globals):
-    """Test --nodes"""
-    sys.argv = ['', '--nodes']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_showNodes():
-        print('inside mocked showNodes')
-    iface.showNodes.side_effect = mock_showNodes
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked showNodes', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_onConnection(reset_globals, capsys) -
-
-

Test onConnection

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_onConnection(reset_globals, capsys):
-    """Test onConnection"""
-    sys.argv = ['']
-    Globals.getInstance().set_args(sys.argv)
-    iface = MagicMock(autospec=SerialInterface)
-    class TempTopic:
-        """ temp class for topic """
-        def getName(self):
-            """ return the fake name of a topic"""
-            return 'foo'
-    mytopic = TempTopic()
-    onConnection(iface, mytopic)
-    out, err = capsys.readouterr()
-    assert re.search(r'Connection changed: foo', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_main_onReceive_empty(caplog, reset_globals) -
-
-

Test onReceive

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_onReceive_empty(caplog, reset_globals):
-    """Test onReceive"""
-    sys.argv = ['']
-    Globals.getInstance().set_args(sys.argv)
-    iface = MagicMock(autospec=SerialInterface)
-    packet = {'decoded': 'foo'}
-    with caplog.at_level(logging.DEBUG):
-        onReceive(packet, iface)
-    assert re.search(r'in onReceive', caplog.text, re.MULTILINE)
-
-
-
-def test_main_onReceive_with_reply(caplog, capsys, reset_globals) -
-
-

Test onReceive with a reply -To capture: on one device run '–sendtext aaa –reply' and on another -device run '–sendtext bbb –reply', then back to the first device and -run '–sendtext aaa2 –reply'. You should now see a "Sending reply" message.

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_onReceive_with_reply(caplog, capsys, reset_globals):
-    """Test onReceive with a reply
-       To capture: on one device run '--sendtext aaa --reply' and on another
-       device run '--sendtext bbb --reply', then back to the first device and
-       run '--sendtext aaa2 --reply'. You should now see a "Sending reply" message.
-    """
-    sys.argv = ['', '--sendtext', 'hello', '--reply']
-    Globals.getInstance().set_args(sys.argv)
-
-    # Note: 'TEXT_MESSAGE_APP' value is 1
-
-    send_packet = {
-            'to': 4294967295,
-            'decoded': {
-                'portnum': 1,
-                'payload': "hello"
-                },
-            'id': 334776977,
-            'hop_limit': 3,
-            'want_ack': True
-            }
-
-    reply_packet = {
-            'from': 682968668,
-            'to': 4294967295,
-            'decoded': {
-                'portnum': 'TEXT_MESSAGE_APP',
-                'payload': b'bbb',
-                'text': 'bbb'
-                },
-            'id': 1709936182,
-            'rxTime': 1640381999,
-            'rxSnr': 6.0,
-            'hopLimit': 3,
-            'raw': 'faked',
-            'fromId': '!28b5465c',
-            'toId': '^all'
-            }
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.myInfo.my_node_num = 4294967295
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with caplog.at_level(logging.DEBUG):
-            main()
-            onReceive(send_packet, iface)
-            onReceive(reply_packet, iface)
-        assert re.search(r'in onReceive', caplog.text, re.MULTILINE)
-        out, err = capsys.readouterr()
-        assert re.search(r'got msg ', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_onReceive_with_sendtext(caplog, reset_globals) -
-
-

Test onReceive with sendtext -The entire point of this test is to make sure the interface.close() call -is made in onReceive().

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_onReceive_with_sendtext(caplog, reset_globals):
-    """Test onReceive with sendtext
-       The entire point of this test is to make sure the interface.close() call
-       is made in onReceive().
-    """
-    sys.argv = ['', '--sendtext', 'hello']
-    Globals.getInstance().set_args(sys.argv)
-
-    # Note: 'TEXT_MESSAGE_APP' value is 1
-    packet = {
-            'to': 4294967295,
-            'decoded': {
-                'portnum': 1,
-                'payload': "hello"
-                },
-            'id': 334776977,
-            'hop_limit': 3,
-            'want_ack': True
-            }
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.myInfo.my_node_num = 4294967295
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with caplog.at_level(logging.DEBUG):
-            main()
-            onReceive(packet, iface)
-        assert re.search(r'in onReceive', caplog.text, re.MULTILINE)
-        mo.assert_called()
-
-
-
-def test_main_pos_fields_arg_of_zero(capsys, reset_globals) -
-
-

Test –pos-fields an arg of 0 (which shows list)

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_pos_fields_arg_of_zero(capsys, reset_globals):
-    """Test --pos-fields an arg of 0 (which shows list)"""
-    sys.argv = ['', '--pos-fields', '0']
-    Globals.getInstance().set_args(sys.argv)
-
-    pos_flags = MagicMock(autospec=meshtastic.radioconfig_pb2.PositionFlags)
-
-    with patch('meshtastic.serial_interface.SerialInterface') as mo:
-        with patch('meshtastic.radioconfig_pb2.PositionFlags', return_value=pos_flags) as mrc:
-
-            def throw_value_error_exception(exc):
-                raise ValueError()
-            mrc.Value.side_effect = throw_value_error_exception
-            mrc.keys.return_value = [ 'POS_UNDEFINED', 'POS_ALTITUDE', 'POS_ALT_MSL',
-                                      'POS_GEO_SEP', 'POS_DOP', 'POS_HVDOP', 'POS_BATTERY',
-                                      'POS_SATINVIEW', 'POS_SEQ_NOS', 'POS_TIMESTAMP']
-
-            main()
-
-            mrc.Value.assert_called()
-            mrc.keys.assert_called()
-            mo.assert_called()
-
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'ERROR: supported position fields are:', out, re.MULTILINE)
-            assert re.search(r"['POS_UNDEFINED', 'POS_ALTITUDE', 'POS_ALT_MSL', 'POS_GEO_SEP',"\
-                              "'POS_DOP', 'POS_HVDOP', 'POS_BATTERY', 'POS_SATINVIEW', 'POS_SEQ_NOS',"\
-                              "'POS_TIMESTAMP']", out, re.MULTILINE)
-            assert err == ''
-
-
-
-def test_main_pos_fields_no_args(capsys, reset_globals) -
-
-

Test –pos-fields no args (which shows settings)

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_pos_fields_no_args(capsys, reset_globals):
-    """Test --pos-fields no args (which shows settings)"""
-    sys.argv = ['', '--pos-fields']
-    Globals.getInstance().set_args(sys.argv)
-
-    pos_flags = MagicMock(autospec=meshtastic.radioconfig_pb2.PositionFlags)
-
-    with patch('meshtastic.serial_interface.SerialInterface') as mo:
-        with patch('meshtastic.radioconfig_pb2.PositionFlags', return_value=pos_flags) as mrc:
-            # kind of cheating here, we are setting up the node
-            mocked_node = MagicMock(autospec=Node)
-            anode = mocked_node()
-            anode.radioConfig.preferences.position_flags = 35
-            Globals.getInstance().set_target_node(anode)
-
-            mrc.values.return_value = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256]
-            # Note: When you use side_effect and a list, each call will use a value from the front of the list then
-            # remove that value from the list. If there are three values in the list, we expect it to be called
-            # three times.
-            mrc.Name.side_effect = [ 'POS_ALTITUDE', 'POS_ALT_MSL', 'POS_BATTERY' ]
-
-            main()
-
-            mrc.Name.assert_called()
-            mrc.values.assert_called()
-            mo.assert_called()
-
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'POS_ALTITUDE POS_ALT_MSL POS_BATTERY', out, re.MULTILINE)
-            assert err == ''
-
-
-
-def test_main_pos_fields_valid_values(capsys, reset_globals) -
-
-

Test –pos-fields with valid values

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_pos_fields_valid_values(capsys, reset_globals):
-    """Test --pos-fields with valid values"""
-    sys.argv = ['', '--pos-fields', 'POS_GEO_SEP', 'POS_ALT_MSL']
-    Globals.getInstance().set_args(sys.argv)
-
-    pos_flags = MagicMock(autospec=meshtastic.radioconfig_pb2.PositionFlags)
-
-    with patch('meshtastic.serial_interface.SerialInterface') as mo:
-        with patch('meshtastic.radioconfig_pb2.PositionFlags', return_value=pos_flags) as mrc:
-
-            mrc.Value.side_effect = [ 4, 2 ]
-
-            main()
-
-            mrc.Value.assert_called()
-            mo.assert_called()
-
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'Setting position fields to 6', out, re.MULTILINE)
-            assert re.search(r'Set position_flags to 6', out, re.MULTILINE)
-            assert re.search(r'Writing modified preferences to device', out, re.MULTILINE)
-            assert err == ''
-
-
-
-def test_main_qr(capsys, reset_globals) -
-
-

Test –qr

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_qr(capsys, reset_globals):
-    """Test --qr"""
-    sys.argv = ['', '--qr']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    # TODO: could mock/check url
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Primary channel URL', out, re.MULTILINE)
-        # if a qr code is generated it will have lots of these
-        assert re.search(r'\[7m', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_reboot(capsys, reset_globals) -
-
-

Test –reboot

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_reboot(capsys, reset_globals):
-    """Test --reboot"""
-    sys.argv = ['', '--reboot']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_reboot():
-        print('inside mocked reboot')
-    mocked_node.reboot.side_effect = mock_reboot
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'inside mocked reboot', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_sendping(capsys, reset_globals) -
-
-

Test –sendping

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_sendping(capsys, reset_globals):
-    """Test --sendping"""
-    sys.argv = ['', '--sendping']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendData(payload, dest, portNum, wantAck, wantResponse):
-        print('inside mocked sendData')
-    iface.sendData.side_effect = mock_sendData
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Sending ping message', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendData', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_sendtext(capsys, reset_globals) -
-
-

Test –sendtext

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_sendtext(capsys, reset_globals):
-    """Test --sendtext"""
-    sys.argv = ['', '--sendtext', 'hello']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendText(text, dest, wantAck, channelIndex):
-        print('inside mocked sendText')
-    iface.sendText.side_effect = mock_sendText
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Sending text message', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendText', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_sendtext_with_channel(capsys, reset_globals) -
-
-

Test –sendtext

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_sendtext_with_channel(capsys, reset_globals):
-    """Test --sendtext"""
-    sys.argv = ['', '--sendtext', 'hello', '--ch-index', '1']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendText(text, dest, wantAck, channelIndex):
-        print('inside mocked sendText')
-    iface.sendText.side_effect = mock_sendText
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Sending text message', out, re.MULTILINE)
-        assert re.search(r'on channelIndex:1', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendText', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_sendtext_with_dest(capsys, reset_globals) -
-
-

Test –sendtext with –dest

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_sendtext_with_dest(capsys, reset_globals):
-    """Test --sendtext with --dest"""
-    sys.argv = ['', '--sendtext', 'hello', '--dest', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendText(text, dest, wantAck, channelIndex):
-        print('inside mocked sendText')
-    iface.sendText.side_effect = mock_sendText
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Sending text message', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendText', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_sendtext_with_invalid_channel(capsys, reset_globals) -
-
-

Test –sendtext

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_sendtext_with_invalid_channel(capsys, reset_globals):
-    """Test --sendtext"""
-    sys.argv = ['', '--sendtext', 'hello', '--ch-index', '-1']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getChannelByChannelIndex.return_value = None
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        iface.getNode.return_value.getChannelByChannelIndex.return_value = None
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'is not a valid channel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_sendtext_with_invalid_channel_nine(capsys, reset_globals) -
-
-

Test –sendtext

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_sendtext_with_invalid_channel_nine(capsys, reset_globals):
-    """Test --sendtext"""
-    sys.argv = ['', '--sendtext', 'hello', '--ch-index', '9']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        iface.getNode.return_value.getChannelByChannelIndex.return_value = None
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.search(r'is not a valid channel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_setPref_invalid_field(capsys, reset_globals) -
-
-

Test setPref() with a invalid field

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_setPref_invalid_field(capsys, reset_globals):
-    """Test setPref() with a invalid field"""
-
-
-    class Field:
-        """Simple class for testing."""
-
-        def __init__(self, name):
-            """constructor"""
-            self.name = name
-
-    prefs = MagicMock()
-    prefs.DESCRIPTOR.fields_by_name.get.return_value = None
-
-    # Note: This is a subset of the real fields
-    ls_secs_field = Field('ls_secs')
-    is_router = Field('is_router')
-    fixed_position = Field('fixed_position')
-
-    fields = [ ls_secs_field, is_router, fixed_position ]
-    prefs.DESCRIPTOR.fields = fields
-
-    setPref(prefs, 'foo', '300')
-    out, err = capsys.readouterr()
-    assert re.search(r'does not have an attribute called foo', out, re.MULTILINE)
-    # ensure they are sorted
-    assert re.search(r'fixed_position\s+is_router\s+ls_secs', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_main_setPref_valid_field(capsys, reset_globals) -
-
-

Test setPref() with a valid field

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_setPref_valid_field(capsys, reset_globals):
-    """Test setPref() with a valid field"""
-
-    class Field:
-        """Simple class for testing."""
-
-        def __init__(self, name, enum_type):
-            """constructor"""
-            self.name = name
-            self.enum_type = enum_type
-
-    ls_secs_field = Field('ls_secs', 'int')
-    prefs = MagicMock()
-    prefs.DESCRIPTOR.fields_by_name.get.return_value = ls_secs_field
-
-    setPref(prefs, 'ls_secs', '300')
-    out, err = capsys.readouterr()
-    assert re.search(r'Set ls_secs to 300', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_main_set_ham_to_KI123(capsys, reset_globals) -
-
-

Test –set-ham KI123

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_set_ham_to_KI123(capsys, reset_globals):
-    """Test --set-ham KI123"""
-    sys.argv = ['', '--set-ham', 'KI123']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_turnOffEncryptionOnPrimaryChannel():
-        print('inside mocked turnOffEncryptionOnPrimaryChannel')
-    def mock_setOwner(name, is_licensed):
-        print('inside mocked setOwner')
-    mocked_node.turnOffEncryptionOnPrimaryChannel.side_effect = mock_turnOffEncryptionOnPrimaryChannel
-    mocked_node.setOwner.side_effect = mock_setOwner
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Setting Ham ID to KI123', out, re.MULTILINE)
-        assert re.search(r'inside mocked setOwner', out, re.MULTILINE)
-        assert re.search(r'inside mocked turnOffEncryptionOnPrimaryChannel', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_set_owner_to_bob(capsys, reset_globals) -
-
-

Test –set-owner bob

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_set_owner_to_bob(capsys, reset_globals):
-    """Test --set-owner bob"""
-    sys.argv = ['', '--set-owner', 'bob']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Setting device owner to bob', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_set_team_invalid(capsys, reset_globals) -
-
-

Test –set-team using an invalid team name

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_set_team_invalid(capsys, reset_globals):
-    """Test --set-team using an invalid team name"""
-    sys.argv = ['', '--set-team', 'NOTCYAN']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-
-    def throw_an_exception(exc):
-        raise ValueError("Fake exception.")
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with patch('meshtastic.mesh_pb2.Team') as mm:
-            mm.Value.side_effect = throw_an_exception
-            main()
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'ERROR: Team', out, re.MULTILINE)
-            assert err == ''
-            mo.assert_called()
-            mm.Value.assert_called()
-
-
-
-def test_main_set_team_valid(capsys, reset_globals) -
-
-

Test –set-team

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_set_team_valid(capsys, reset_globals):
-    """Test --set-team"""
-    sys.argv = ['', '--set-team', 'CYAN']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_setOwner(team):
-        print('inside mocked setOwner')
-    mocked_node.setOwner.side_effect = mock_setOwner
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.localNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with patch('meshtastic.mesh_pb2.Team') as mm:
-            mm.Name.return_value = 'FAKENAME'
-            mm.Value.return_value = 'FAKEVAL'
-            main()
-            out, err = capsys.readouterr()
-            assert re.search(r'Connected to radio', out, re.MULTILINE)
-            assert re.search(r'Setting team to', out, re.MULTILINE)
-            assert err == ''
-            mo.assert_called()
-            mm.Name.assert_called()
-            mm.Value.assert_called()
-
-
-
-def test_main_set_valid(capsys, reset_globals) -
-
-

Test –set with valid field

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_set_valid(capsys, reset_globals):
-    """Test --set with valid field"""
-    sys.argv = ['', '--set', 'wifi_ssid', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Set wifi_ssid to foo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_set_with_invalid(capsys, reset_globals) -
-
-

Test –set with invalid field

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_set_with_invalid(capsys, reset_globals):
-    """Test --set with invalid field"""
-    sys.argv = ['', '--set', 'foo', 'foo']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_user_prefs = MagicMock()
-    mocked_user_prefs.DESCRIPTOR.fields_by_name.get.return_value = None
-
-    mocked_node = MagicMock(autospec=Node)
-    mocked_node.radioConfig.preferences = ( mocked_user_prefs )
-
-    iface = MagicMock(autospec=SerialInterface)
-    iface.getNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'does not have an attribute called foo', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_setalt(capsys, reset_globals) -
-
-

Test –setalt

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_setalt(capsys, reset_globals):
-    """Test --setalt"""
-    sys.argv = ['', '--setalt', '51']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_writeConfig():
-        print('inside mocked writeConfig')
-    mocked_node.writeConfig.side_effect = mock_writeConfig
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendPosition(lat, lon, alt):
-        print('inside mocked sendPosition')
-    iface.sendPosition.side_effect = mock_sendPosition
-    iface.localNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Fixing altitude', out, re.MULTILINE)
-        assert re.search(r'Setting device position', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendPosition', out, re.MULTILINE)
-        # TODO: Why does this not work? assert re.search(r'inside mocked writeConfig', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_setchan(capsys, reset_globals) -
-
-

Test –setchan (deprecated)

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_setchan(capsys, reset_globals):
-    """Test --setchan (deprecated)"""
-    sys.argv = ['', '--setchan', 'a', 'b']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface):
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            main()
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-
-
-
-def test_main_setlat(capsys, reset_globals) -
-
-

Test –sendlat

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_setlat(capsys, reset_globals):
-    """Test --sendlat"""
-    sys.argv = ['', '--setlat', '37.5']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_writeConfig():
-        print('inside mocked writeConfig')
-    mocked_node.writeConfig.side_effect = mock_writeConfig
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendPosition(lat, lon, alt):
-        print('inside mocked sendPosition')
-    iface.sendPosition.side_effect = mock_sendPosition
-    iface.localNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Fixing latitude', out, re.MULTILINE)
-        assert re.search(r'Setting device position', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendPosition', out, re.MULTILINE)
-        # TODO: Why does this not work? assert re.search(r'inside mocked writeConfig', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_setlon(capsys, reset_globals) -
-
-

Test –setlon

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_setlon(capsys, reset_globals):
-    """Test --setlon"""
-    sys.argv = ['', '--setlon', '-122.1']
-    Globals.getInstance().set_args(sys.argv)
-
-    mocked_node = MagicMock(autospec=Node)
-    def mock_writeConfig():
-        print('inside mocked writeConfig')
-    mocked_node.writeConfig.side_effect = mock_writeConfig
-
-    iface = MagicMock(autospec=SerialInterface)
-    def mock_sendPosition(lat, lon, alt):
-        print('inside mocked sendPosition')
-    iface.sendPosition.side_effect = mock_sendPosition
-    iface.localNode.return_value = mocked_node
-
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert re.search(r'Fixing longitude', out, re.MULTILINE)
-        assert re.search(r'Setting device position', out, re.MULTILINE)
-        assert re.search(r'inside mocked sendPosition', out, re.MULTILINE)
-        # TODO: Why does this not work? assert re.search(r'inside mocked writeConfig', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_seturl(capsys, reset_globals) -
-
-

Test –seturl (url used below is what is generated after a factory_reset)

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_seturl(capsys, reset_globals):
-    """Test --seturl (url used below is what is generated after a factory_reset)"""
-    sys.argv = ['', '--seturl', 'https://www.meshtastic.org/d/#CgUYAyIBAQ']
-    Globals.getInstance().set_args(sys.argv)
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        main()
-        out, err = capsys.readouterr()
-        assert re.search(r'Connected to radio', out, re.MULTILINE)
-        assert err == ''
-        mo.assert_called()
-
-
-
-def test_main_support(capsys, reset_globals) -
-
-

Test –support

-
- -Expand source code - -
@pytest.mark.unit
-def test_main_support(capsys, reset_globals):
-    """Test --support"""
-    sys.argv = ['', '--support']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-    out, err = capsys.readouterr()
-    assert re.search(r'System', out, re.MULTILINE)
-    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 == ''
-
-
-
-def test_main_test_no_ports(patched_find_ports, reset_globals) -
-
-

Test –test with no hardware

-
- -Expand source code - -
@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=[])
-def test_main_test_no_ports(patched_find_ports, reset_globals):
-    """Test --test with no hardware"""
-    sys.argv = ['', '--test']
-    Globals.getInstance().set_args(sys.argv)
-
-    assert Globals.getInstance().get_target_node() is None
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    patched_find_ports.assert_called()
-
-
-
-def test_main_test_one_port(patched_find_ports, reset_globals) -
-
-

Test –test with one fake port

-
- -Expand source code - -
@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyFake1'])
-def test_main_test_one_port(patched_find_ports, reset_globals):
-    """Test --test with one fake port"""
-    sys.argv = ['', '--test']
-    Globals.getInstance().set_args(sys.argv)
-
-    assert Globals.getInstance().get_target_node() is None
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    patched_find_ports.assert_called()
-
-
-
-def test_main_test_two_ports_fails(patched_find_ports, patched_test_all, reset_globals) -
-
-

Test –test two fake ports and testAll() is a simulated failure

-
- -Expand source code - -
@pytest.mark.unit
-@patch('meshtastic.test.testAll', return_value=False)
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyFake1', '/dev/ttyFake2'])
-def test_main_test_two_ports_fails(patched_find_ports, patched_test_all, reset_globals):
-    """Test --test two fake ports and testAll() is a simulated failure"""
-    sys.argv = ['', '--test']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    # TODO: why does this fail? patched_find_ports.assert_called()
-    patched_test_all.assert_called()
-
-
-
-def test_main_test_two_ports_success(patched_find_ports, patched_test_all, reset_globals) -
-
-

Test –test two fake ports and testAll() is a simulated success

-
- -Expand source code - -
@pytest.mark.unit
-@patch('meshtastic.test.testAll', return_value=True)
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyFake1', '/dev/ttyFake2'])
-def test_main_test_two_ports_success(patched_find_ports, patched_test_all, reset_globals):
-    """Test --test two fake ports and testAll() is a simulated success"""
-    sys.argv = ['', '--test']
-    Globals.getInstance().set_args(sys.argv)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        main()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-    # TODO: why does this fail? patched_find_ports.assert_called()
-    patched_test_all.assert_called()
-
-
-
-
-
-

Classes

-
-
-class Channel -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var DISABLED
-
-
-
-
var INDEX_FIELD_NUMBER
-
-
-
-
var PRIMARY
-
-
-
-
var ROLE_FIELD_NUMBER
-
-
-
-
var Role
-
-
-
-
var SECONDARY
-
-
-
-
var SETTINGS_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var index
-
-

Getter for index.

-
- -Expand source code - -
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)
-
-
-
var role
-
-

Getter for role.

-
- -Expand source code - -
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)
-
-
-
var settings
-
-

Getter for settings.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_mesh_interface.html b/docs/meshtastic/tests/test_mesh_interface.html deleted file mode 100644 index 06b366e..0000000 --- a/docs/meshtastic/tests/test_mesh_interface.html +++ /dev/null @@ -1,1290 +0,0 @@ - - - - - - -meshtastic.tests.test_mesh_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_mesh_interface

-
-
-

Meshtastic unit tests for mesh_interface.py

-
- -Expand source code - -
"""Meshtastic unit tests for mesh_interface.py"""
-
-import re
-import logging
-
-from unittest.mock import patch, MagicMock
-import pytest
-
-from ..mesh_interface import MeshInterface
-from ..node import Node
-from .. import mesh_pb2
-from ..__init__ import LOCAL_ADDR, BROADCAST_ADDR
-
-
-@pytest.mark.unit
-def test_MeshInterface(capsys, reset_globals):
-    """Test that we can instantiate a MeshInterface"""
-    iface = MeshInterface(noProto=True)
-    anode = Node('foo', 'bar')
-
-    nodes = {
-        '!9388f81c': {
-            'num': 2475227164,
-            'user': {
-                'id': '!9388f81c',
-                'longName': 'Unknown f81c',
-                'shortName': '?1C',
-                'macaddr': 'RBeTiPgc',
-                'hwModel': 'TBEAM'
-            },
-            'position': {},
-            'lastHeard': 1640204888
-        }
-    }
-
-    iface.nodesByNum = {1: anode }
-    iface.nodes = nodes
-
-    myInfo = MagicMock()
-    iface.myInfo = myInfo
-
-    iface.showInfo()
-    iface.localNode.showInfo()
-    iface.showNodes()
-    iface.sendText('hello')
-    iface.close()
-    out, err = capsys.readouterr()
-    assert re.search(r'Owner: None \(None\)', out, re.MULTILINE)
-    assert re.search(r'Nodes', out, re.MULTILINE)
-    assert re.search(r'Preferences', out, re.MULTILINE)
-    assert re.search(r'Channels', out, re.MULTILINE)
-    assert re.search(r'Primary channel URL', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_getMyUser(reset_globals, iface_with_nodes):
-    """Test getMyUser()"""
-    iface = iface_with_nodes
-
-    iface.myInfo.my_node_num = 2475227164
-    myuser = iface.getMyUser()
-    print(f'myuser:{myuser}')
-    assert myuser is not None
-    assert myuser["id"] == '!9388f81c'
-
-
-@pytest.mark.unit
-def test_getLongName(reset_globals, iface_with_nodes):
-    """Test getLongName()"""
-    iface = iface_with_nodes
-    iface.myInfo.my_node_num = 2475227164
-    mylongname = iface.getLongName()
-    assert mylongname == 'Unknown f81c'
-
-
-@pytest.mark.unit
-def test_getShortName(reset_globals, iface_with_nodes):
-    """Test getShortName()."""
-    iface = iface_with_nodes
-    iface.myInfo.my_node_num = 2475227164
-    myshortname = iface.getShortName()
-    assert myshortname == '?1C'
-
-
-@pytest.mark.unit
-def test_handlePacketFromRadio_no_from(capsys, reset_globals):
-    """Test _handlePacketFromRadio with no 'from' in the mesh packet."""
-    iface = MeshInterface(noProto=True)
-    meshPacket = mesh_pb2.MeshPacket()
-    iface._handlePacketFromRadio(meshPacket)
-    out, err = capsys.readouterr()
-    assert re.search(r'Device returned a packet we sent, ignoring', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_handlePacketFromRadio_with_a_portnum(caplog, reset_globals):
-    """Test _handlePacketFromRadio with a portnum
-       Since we have an attribute called 'from', we cannot simply 'set' it.
-       Had to implement a hack just to be able to test some code.
-    """
-    iface = MeshInterface(noProto=True)
-    meshPacket = mesh_pb2.MeshPacket()
-    meshPacket.decoded.payload = b''
-    meshPacket.decoded.portnum = 1
-    with caplog.at_level(logging.WARNING):
-        iface._handlePacketFromRadio(meshPacket, hack=True)
-    assert re.search(r'Not populating fromId', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_handlePacketFromRadio_no_portnum(caplog, reset_globals):
-    """Test _handlePacketFromRadio without a portnum"""
-    iface = MeshInterface(noProto=True)
-    meshPacket = mesh_pb2.MeshPacket()
-    meshPacket.decoded.payload = b''
-    with caplog.at_level(logging.WARNING):
-        iface._handlePacketFromRadio(meshPacket, hack=True)
-    assert re.search(r'Not populating fromId', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_getNode_with_local(reset_globals):
-    """Test getNode"""
-    iface = MeshInterface(noProto=True)
-    anode = iface.getNode(LOCAL_ADDR)
-    assert anode == iface.localNode
-
-
-@pytest.mark.unit
-def test_getNode_not_local(reset_globals, caplog):
-    """Test getNode not local"""
-    iface = MeshInterface(noProto=True)
-    anode = MagicMock(autospec=Node)
-    with caplog.at_level(logging.DEBUG):
-        with patch('meshtastic.node.Node', return_value=anode):
-            another_node = iface.getNode('bar2')
-            assert another_node != iface.localNode
-    assert re.search(r'About to requestConfig', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_getNode_not_local_timeout(reset_globals, capsys):
-    """Test getNode not local, simulate timeout"""
-    iface = MeshInterface(noProto=True)
-    anode = MagicMock(autospec=Node)
-    anode.waitForConfig.return_value = False
-    with patch('meshtastic.node.Node', return_value=anode):
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            iface.getNode('bar2')
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.match(r'Error: Timed out waiting for node config', out)
-        assert err == ''
-
-
-@pytest.mark.unit
-def test_sendPosition(reset_globals, caplog):
-    """Test sendPosition"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface.sendPosition()
-    iface.close()
-    assert re.search(r'p.time:', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_handleFromRadio_empty_payload(reset_globals, caplog):
-    """Test _handleFromRadio"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._handleFromRadio(b'')
-    iface.close()
-    assert re.search(r'Unexpected FromRadio payload', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_handleFromRadio_with_my_info(reset_globals, caplog):
-    """Test _handleFromRadio with my_info"""
-    # Note: I captured the '--debug --info' for the bytes below.
-    # It "translates" to this:
-    # my_info {
-    #  my_node_num: 682584012
-    #  num_bands: 13
-    #  firmware_version: "1.2.49.5354c49"
-    #  reboot_count: 13
-    #  bitrate: 17.088470458984375
-    #  message_timeout_msec: 300000
-    #  min_app_version: 20200
-    #  max_channels: 8
-    # }
-    from_radio_bytes = b'\x1a,\x08\xcc\xcf\xbd\xc5\x02\x18\r2\x0e1.2.49.5354c49P\r]0\xb5\x88Ah\xe0\xa7\x12p\xe8\x9d\x01x\x08\x90\x01\x01'
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._handleFromRadio(from_radio_bytes)
-    iface.close()
-    assert re.search(r'Received myinfo', caplog.text, re.MULTILINE)
-    assert re.search(r'num_bands: 13', caplog.text, re.MULTILINE)
-    assert re.search(r'max_channels: 8', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_handleFromRadio_with_node_info(reset_globals, caplog, capsys):
-    """Test _handleFromRadio with node_info"""
-    # Note: I captured the '--debug --info' for the bytes below.
-    # It "translates" to this:
-    # node_info {
-    #  num: 682584012
-    #  user {
-    #    id: "!28af67cc"
-    #    long_name: "Unknown 67cc"
-    #    short_name: "?CC"
-    #    macaddr: "$o(\257g\314"
-    #    hw_model: HELTEC_V2_1
-    #  }
-    #  position {
-    #    }
-    #  }
-
-    from_radio_bytes = b'"2\x08\xcc\xcf\xbd\xc5\x02\x12(\n\t!28af67cc\x12\x0cUnknown 67cc\x1a\x03?CC"\x06$o(\xafg\xcc0\n\x1a\x00'
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._startConfig()
-        iface._handleFromRadio(from_radio_bytes)
-        assert re.search(r'Received nodeinfo', caplog.text, re.MULTILINE)
-        assert re.search(r'682584012', caplog.text, re.MULTILINE)
-        assert re.search(r'HELTEC_V2_1', caplog.text, re.MULTILINE)
-        # validate some of showNodes() output
-        iface.showNodes()
-        out, err = capsys.readouterr()
-        assert re.search(r' 1 ', out, re.MULTILINE)
-        assert re.search(r'│ Unknown 67cc │ ', out, re.MULTILINE)
-        assert re.search(r'│ !28af67cc │ N/A   │ N/A         │ N/A', out, re.MULTILINE)
-        assert err == ''
-        iface.close()
-
-
-@pytest.mark.unit
-def test_handleFromRadio_with_node_info_tbeam1(reset_globals, caplog, capsys):
-    """Test _handleFromRadio with node_info"""
-    # Note: Captured the '--debug --info' for the bytes below.
-    # pylint: disable=C0301
-    from_radio_bytes = b'"=\x08\x80\xf8\xc8\xf6\x07\x12"\n\t!7ed23c00\x12\x07TBeam 1\x1a\x02T1"\x06\x94\xb9~\xd2<\x000\x04\x1a\x07 ]MN\x01\xbea%\xad\x01\xbea=\x00\x00,A'
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._startConfig()
-        iface._handleFromRadio(from_radio_bytes)
-        assert re.search(r'Received nodeinfo', caplog.text, re.MULTILINE)
-        assert re.search(r'TBeam 1', caplog.text, re.MULTILINE)
-        assert re.search(r'2127707136', caplog.text, re.MULTILINE)
-        # validate some of showNodes() output
-        iface.showNodes()
-        out, err = capsys.readouterr()
-        assert re.search(r' 1 ', out, re.MULTILINE)
-        assert re.search(r'│ TBeam 1 │ ', out, re.MULTILINE)
-        assert re.search(r'│ !7ed23c00 │', out, re.MULTILINE)
-        assert err == ''
-        iface.close()
-
-
-@pytest.mark.unit
-def test_handleFromRadio_with_node_info_tbeam_with_bad_data(reset_globals, caplog, capsys):
-    """Test _handleFromRadio with node_info with some bad data (issue#172) - ensure we do not throw exception"""
-    # Note: Captured the '--debug --info' for the bytes below.
-    from_radio_bytes = b'"\x17\x08\xdc\x8a\x8a\xae\x02\x12\x08"\x06\x00\x00\x00\x00\x00\x00\x1a\x00=\x00\x00\xb8@'
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._startConfig()
-        iface._handleFromRadio(from_radio_bytes)
-
-
-@pytest.mark.unit
-def test_MeshInterface_sendToRadioImpl(caplog, reset_globals):
-    """Test _sendToRadioImp()"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._sendToRadioImpl('foo')
-    assert re.search(r'Subclass must provide toradio', caplog.text, re.MULTILINE)
-    iface.close()
-
-
-@pytest.mark.unit
-def test_MeshInterface_sendToRadio_no_proto(caplog, reset_globals):
-    """Test sendToRadio()"""
-    iface = MeshInterface()
-    with caplog.at_level(logging.DEBUG):
-        iface._sendToRadioImpl('foo')
-    assert re.search(r'Subclass must provide toradio', caplog.text, re.MULTILINE)
-    iface.close()
-
-
-@pytest.mark.unit
-def test_sendData_too_long(caplog, reset_globals):
-    """Test when data payload is too big"""
-    iface = MeshInterface(noProto=True)
-    some_large_text = b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    with caplog.at_level(logging.DEBUG):
-        with pytest.raises(Exception) as pytest_wrapped_e:
-            iface.sendData(some_large_text)
-            assert re.search('Data payload too big', caplog.text, re.MULTILINE)
-        assert pytest_wrapped_e.type == Exception
-    iface.close()
-
-
-@pytest.mark.unit
-def test_sendData_unknown_app(capsys, reset_globals):
-    """Test sendData when unknown app"""
-    iface = MeshInterface(noProto=True)
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        iface.sendData(b'hello', portNum=0)
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: A non-zero port number', out, re.MULTILINE)
-    assert err == ''
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-@pytest.mark.unit
-def test_sendPosition_with_a_position(caplog, reset_globals):
-    """Test sendPosition when lat/long/alt"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface.sendPosition(latitude=40.8, longitude=-111.86, altitude=201)
-        assert re.search(r'p.latitude_i:408', caplog.text, re.MULTILINE)
-        assert re.search(r'p.longitude_i:-11186', caplog.text, re.MULTILINE)
-        assert re.search(r'p.altitude:201', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_sendPacket_with_no_destination(capsys, reset_globals):
-    """Test _sendPacket()"""
-    iface = MeshInterface(noProto=True)
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        iface._sendPacket(b'', destinationId=None)
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: destinationId must not be None', out, re.MULTILINE)
-    assert err == ''
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-@pytest.mark.unit
-def test_sendPacket_with_destination_as_int(caplog, reset_globals):
-    """Test _sendPacket() with int as a destination"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId=123)
-        assert re.search(r'Not sending packet', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_sendPacket_with_destination_starting_with_a_bang(caplog, reset_globals):
-    """Test _sendPacket() with int as a destination"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId='!1234')
-        assert re.search(r'Not sending packet', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_sendPacket_with_destination_as_BROADCAST_ADDR(caplog, reset_globals):
-    """Test _sendPacket() with BROADCAST_ADDR as a destination"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId=BROADCAST_ADDR)
-        assert re.search(r'Not sending packet', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_sendPacket_with_destination_as_LOCAL_ADDR_no_myInfo(capsys, reset_globals):
-    """Test _sendPacket() with LOCAL_ADDR as a destination with no myInfo"""
-    iface = MeshInterface(noProto=True)
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId=LOCAL_ADDR)
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: No myInfo', out, re.MULTILINE)
-    assert err == ''
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-@pytest.mark.unit
-def test_sendPacket_with_destination_as_LOCAL_ADDR_with_myInfo(caplog, reset_globals):
-    """Test _sendPacket() with LOCAL_ADDR as a destination with myInfo"""
-    iface = MeshInterface(noProto=True)
-    myInfo = MagicMock()
-    iface.myInfo = myInfo
-    with caplog.at_level(logging.DEBUG):
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId=LOCAL_ADDR)
-        assert re.search(r'Not sending packet', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_sendPacket_with_destination_is_blank_with_nodes(capsys, reset_globals, iface_with_nodes):
-    """Test _sendPacket() with '' as a destination with myInfo"""
-    iface = iface_with_nodes
-    meshPacket = mesh_pb2.MeshPacket()
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        iface._sendPacket(meshPacket, destinationId='')
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.match(r'Warning: NodeId  not found in DB', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_sendPacket_with_destination_is_blank_without_nodes(caplog, reset_globals, iface_with_nodes):
-    """Test _sendPacket() with '' as a destination with myInfo"""
-    iface = iface_with_nodes
-    iface.nodes = None
-    meshPacket = mesh_pb2.MeshPacket()
-    with caplog.at_level(logging.WARNING):
-        iface._sendPacket(meshPacket, destinationId='')
-    assert re.search(r'Warning: There were no self.nodes.', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_getMyNodeInfo(reset_globals):
-    """Test getMyNodeInfo()"""
-    iface = MeshInterface(noProto=True)
-    anode = iface.getNode(LOCAL_ADDR)
-    iface.nodesByNum = {1: anode }
-    assert iface.nodesByNum.get(1) == anode
-    myInfo = MagicMock()
-    iface.myInfo = myInfo
-    iface.myInfo.my_node_num = 1
-    myinfo = iface.getMyNodeInfo()
-    assert myinfo == anode
-
-
-@pytest.mark.unit
-def test_generatePacketId(capsys, reset_globals):
-    """Test _generatePacketId() when no currentPacketId (not connected)"""
-    iface = MeshInterface(noProto=True)
-    # not sure when this condition would ever happen... but we can simulate it
-    iface.currentPacketId = None
-    assert iface.currentPacketId is None
-    with pytest.raises(Exception) as pytest_wrapped_e:
-        iface._generatePacketId()
-        out, err = capsys.readouterr()
-        assert re.search(r'Not connected yet, can not generate packet', out, re.MULTILINE)
-        assert err == ''
-    assert pytest_wrapped_e.type == Exception
-
-
-
-
-
-
-
-

Functions

-
-
-def test_MeshInterface(capsys, reset_globals) -
-
-

Test that we can instantiate a MeshInterface

-
- -Expand source code - -
@pytest.mark.unit
-def test_MeshInterface(capsys, reset_globals):
-    """Test that we can instantiate a MeshInterface"""
-    iface = MeshInterface(noProto=True)
-    anode = Node('foo', 'bar')
-
-    nodes = {
-        '!9388f81c': {
-            'num': 2475227164,
-            'user': {
-                'id': '!9388f81c',
-                'longName': 'Unknown f81c',
-                'shortName': '?1C',
-                'macaddr': 'RBeTiPgc',
-                'hwModel': 'TBEAM'
-            },
-            'position': {},
-            'lastHeard': 1640204888
-        }
-    }
-
-    iface.nodesByNum = {1: anode }
-    iface.nodes = nodes
-
-    myInfo = MagicMock()
-    iface.myInfo = myInfo
-
-    iface.showInfo()
-    iface.localNode.showInfo()
-    iface.showNodes()
-    iface.sendText('hello')
-    iface.close()
-    out, err = capsys.readouterr()
-    assert re.search(r'Owner: None \(None\)', out, re.MULTILINE)
-    assert re.search(r'Nodes', out, re.MULTILINE)
-    assert re.search(r'Preferences', out, re.MULTILINE)
-    assert re.search(r'Channels', out, re.MULTILINE)
-    assert re.search(r'Primary channel URL', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_MeshInterface_sendToRadioImpl(caplog, reset_globals) -
-
-

Test _sendToRadioImp()

-
- -Expand source code - -
@pytest.mark.unit
-def test_MeshInterface_sendToRadioImpl(caplog, reset_globals):
-    """Test _sendToRadioImp()"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._sendToRadioImpl('foo')
-    assert re.search(r'Subclass must provide toradio', caplog.text, re.MULTILINE)
-    iface.close()
-
-
-
-def test_MeshInterface_sendToRadio_no_proto(caplog, reset_globals) -
-
-

Test sendToRadio()

-
- -Expand source code - -
@pytest.mark.unit
-def test_MeshInterface_sendToRadio_no_proto(caplog, reset_globals):
-    """Test sendToRadio()"""
-    iface = MeshInterface()
-    with caplog.at_level(logging.DEBUG):
-        iface._sendToRadioImpl('foo')
-    assert re.search(r'Subclass must provide toradio', caplog.text, re.MULTILINE)
-    iface.close()
-
-
-
-def test_generatePacketId(capsys, reset_globals) -
-
-

Test _generatePacketId() when no currentPacketId (not connected)

-
- -Expand source code - -
@pytest.mark.unit
-def test_generatePacketId(capsys, reset_globals):
-    """Test _generatePacketId() when no currentPacketId (not connected)"""
-    iface = MeshInterface(noProto=True)
-    # not sure when this condition would ever happen... but we can simulate it
-    iface.currentPacketId = None
-    assert iface.currentPacketId is None
-    with pytest.raises(Exception) as pytest_wrapped_e:
-        iface._generatePacketId()
-        out, err = capsys.readouterr()
-        assert re.search(r'Not connected yet, can not generate packet', out, re.MULTILINE)
-        assert err == ''
-    assert pytest_wrapped_e.type == Exception
-
-
-
-def test_getLongName(reset_globals, iface_with_nodes) -
-
-

Test getLongName()

-
- -Expand source code - -
@pytest.mark.unit
-def test_getLongName(reset_globals, iface_with_nodes):
-    """Test getLongName()"""
-    iface = iface_with_nodes
-    iface.myInfo.my_node_num = 2475227164
-    mylongname = iface.getLongName()
-    assert mylongname == 'Unknown f81c'
-
-
-
-def test_getMyNodeInfo(reset_globals) -
-
-

Test getMyNodeInfo()

-
- -Expand source code - -
@pytest.mark.unit
-def test_getMyNodeInfo(reset_globals):
-    """Test getMyNodeInfo()"""
-    iface = MeshInterface(noProto=True)
-    anode = iface.getNode(LOCAL_ADDR)
-    iface.nodesByNum = {1: anode }
-    assert iface.nodesByNum.get(1) == anode
-    myInfo = MagicMock()
-    iface.myInfo = myInfo
-    iface.myInfo.my_node_num = 1
-    myinfo = iface.getMyNodeInfo()
-    assert myinfo == anode
-
-
-
-def test_getMyUser(reset_globals, iface_with_nodes) -
-
-

Test getMyUser()

-
- -Expand source code - -
@pytest.mark.unit
-def test_getMyUser(reset_globals, iface_with_nodes):
-    """Test getMyUser()"""
-    iface = iface_with_nodes
-
-    iface.myInfo.my_node_num = 2475227164
-    myuser = iface.getMyUser()
-    print(f'myuser:{myuser}')
-    assert myuser is not None
-    assert myuser["id"] == '!9388f81c'
-
-
-
-def test_getNode_not_local(reset_globals, caplog) -
-
-

Test getNode not local

-
- -Expand source code - -
@pytest.mark.unit
-def test_getNode_not_local(reset_globals, caplog):
-    """Test getNode not local"""
-    iface = MeshInterface(noProto=True)
-    anode = MagicMock(autospec=Node)
-    with caplog.at_level(logging.DEBUG):
-        with patch('meshtastic.node.Node', return_value=anode):
-            another_node = iface.getNode('bar2')
-            assert another_node != iface.localNode
-    assert re.search(r'About to requestConfig', caplog.text, re.MULTILINE)
-
-
-
-def test_getNode_not_local_timeout(reset_globals, capsys) -
-
-

Test getNode not local, simulate timeout

-
- -Expand source code - -
@pytest.mark.unit
-def test_getNode_not_local_timeout(reset_globals, capsys):
-    """Test getNode not local, simulate timeout"""
-    iface = MeshInterface(noProto=True)
-    anode = MagicMock(autospec=Node)
-    anode.waitForConfig.return_value = False
-    with patch('meshtastic.node.Node', return_value=anode):
-        with pytest.raises(SystemExit) as pytest_wrapped_e:
-            iface.getNode('bar2')
-        assert pytest_wrapped_e.type == SystemExit
-        assert pytest_wrapped_e.value.code == 1
-        out, err = capsys.readouterr()
-        assert re.match(r'Error: Timed out waiting for node config', out)
-        assert err == ''
-
-
-
-def test_getNode_with_local(reset_globals) -
-
-

Test getNode

-
- -Expand source code - -
@pytest.mark.unit
-def test_getNode_with_local(reset_globals):
-    """Test getNode"""
-    iface = MeshInterface(noProto=True)
-    anode = iface.getNode(LOCAL_ADDR)
-    assert anode == iface.localNode
-
-
-
-def test_getShortName(reset_globals, iface_with_nodes) -
-
-

Test getShortName().

-
- -Expand source code - -
@pytest.mark.unit
-def test_getShortName(reset_globals, iface_with_nodes):
-    """Test getShortName()."""
-    iface = iface_with_nodes
-    iface.myInfo.my_node_num = 2475227164
-    myshortname = iface.getShortName()
-    assert myshortname == '?1C'
-
-
-
-def test_handleFromRadio_empty_payload(reset_globals, caplog) -
-
-

Test _handleFromRadio

-
- -Expand source code - -
@pytest.mark.unit
-def test_handleFromRadio_empty_payload(reset_globals, caplog):
-    """Test _handleFromRadio"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._handleFromRadio(b'')
-    iface.close()
-    assert re.search(r'Unexpected FromRadio payload', caplog.text, re.MULTILINE)
-
-
-
-def test_handleFromRadio_with_my_info(reset_globals, caplog) -
-
-

Test _handleFromRadio with my_info

-
- -Expand source code - -
@pytest.mark.unit
-def test_handleFromRadio_with_my_info(reset_globals, caplog):
-    """Test _handleFromRadio with my_info"""
-    # Note: I captured the '--debug --info' for the bytes below.
-    # It "translates" to this:
-    # my_info {
-    #  my_node_num: 682584012
-    #  num_bands: 13
-    #  firmware_version: "1.2.49.5354c49"
-    #  reboot_count: 13
-    #  bitrate: 17.088470458984375
-    #  message_timeout_msec: 300000
-    #  min_app_version: 20200
-    #  max_channels: 8
-    # }
-    from_radio_bytes = b'\x1a,\x08\xcc\xcf\xbd\xc5\x02\x18\r2\x0e1.2.49.5354c49P\r]0\xb5\x88Ah\xe0\xa7\x12p\xe8\x9d\x01x\x08\x90\x01\x01'
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._handleFromRadio(from_radio_bytes)
-    iface.close()
-    assert re.search(r'Received myinfo', caplog.text, re.MULTILINE)
-    assert re.search(r'num_bands: 13', caplog.text, re.MULTILINE)
-    assert re.search(r'max_channels: 8', caplog.text, re.MULTILINE)
-
-
-
-def test_handleFromRadio_with_node_info(reset_globals, caplog, capsys) -
-
-

Test _handleFromRadio with node_info

-
- -Expand source code - -
@pytest.mark.unit
-def test_handleFromRadio_with_node_info(reset_globals, caplog, capsys):
-    """Test _handleFromRadio with node_info"""
-    # Note: I captured the '--debug --info' for the bytes below.
-    # It "translates" to this:
-    # node_info {
-    #  num: 682584012
-    #  user {
-    #    id: "!28af67cc"
-    #    long_name: "Unknown 67cc"
-    #    short_name: "?CC"
-    #    macaddr: "$o(\257g\314"
-    #    hw_model: HELTEC_V2_1
-    #  }
-    #  position {
-    #    }
-    #  }
-
-    from_radio_bytes = b'"2\x08\xcc\xcf\xbd\xc5\x02\x12(\n\t!28af67cc\x12\x0cUnknown 67cc\x1a\x03?CC"\x06$o(\xafg\xcc0\n\x1a\x00'
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._startConfig()
-        iface._handleFromRadio(from_radio_bytes)
-        assert re.search(r'Received nodeinfo', caplog.text, re.MULTILINE)
-        assert re.search(r'682584012', caplog.text, re.MULTILINE)
-        assert re.search(r'HELTEC_V2_1', caplog.text, re.MULTILINE)
-        # validate some of showNodes() output
-        iface.showNodes()
-        out, err = capsys.readouterr()
-        assert re.search(r' 1 ', out, re.MULTILINE)
-        assert re.search(r'│ Unknown 67cc │ ', out, re.MULTILINE)
-        assert re.search(r'│ !28af67cc │ N/A   │ N/A         │ N/A', out, re.MULTILINE)
-        assert err == ''
-        iface.close()
-
-
-
-def test_handleFromRadio_with_node_info_tbeam1(reset_globals, caplog, capsys) -
-
-

Test _handleFromRadio with node_info

-
- -Expand source code - -
@pytest.mark.unit
-def test_handleFromRadio_with_node_info_tbeam1(reset_globals, caplog, capsys):
-    """Test _handleFromRadio with node_info"""
-    # Note: Captured the '--debug --info' for the bytes below.
-    # pylint: disable=C0301
-    from_radio_bytes = b'"=\x08\x80\xf8\xc8\xf6\x07\x12"\n\t!7ed23c00\x12\x07TBeam 1\x1a\x02T1"\x06\x94\xb9~\xd2<\x000\x04\x1a\x07 ]MN\x01\xbea%\xad\x01\xbea=\x00\x00,A'
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._startConfig()
-        iface._handleFromRadio(from_radio_bytes)
-        assert re.search(r'Received nodeinfo', caplog.text, re.MULTILINE)
-        assert re.search(r'TBeam 1', caplog.text, re.MULTILINE)
-        assert re.search(r'2127707136', caplog.text, re.MULTILINE)
-        # validate some of showNodes() output
-        iface.showNodes()
-        out, err = capsys.readouterr()
-        assert re.search(r' 1 ', out, re.MULTILINE)
-        assert re.search(r'│ TBeam 1 │ ', out, re.MULTILINE)
-        assert re.search(r'│ !7ed23c00 │', out, re.MULTILINE)
-        assert err == ''
-        iface.close()
-
-
-
-def test_handleFromRadio_with_node_info_tbeam_with_bad_data(reset_globals, caplog, capsys) -
-
-

Test _handleFromRadio with node_info with some bad data (issue#172) - ensure we do not throw exception

-
- -Expand source code - -
@pytest.mark.unit
-def test_handleFromRadio_with_node_info_tbeam_with_bad_data(reset_globals, caplog, capsys):
-    """Test _handleFromRadio with node_info with some bad data (issue#172) - ensure we do not throw exception"""
-    # Note: Captured the '--debug --info' for the bytes below.
-    from_radio_bytes = b'"\x17\x08\xdc\x8a\x8a\xae\x02\x12\x08"\x06\x00\x00\x00\x00\x00\x00\x1a\x00=\x00\x00\xb8@'
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface._startConfig()
-        iface._handleFromRadio(from_radio_bytes)
-
-
-
-def test_handlePacketFromRadio_no_from(capsys, reset_globals) -
-
-

Test _handlePacketFromRadio with no 'from' in the mesh packet.

-
- -Expand source code - -
@pytest.mark.unit
-def test_handlePacketFromRadio_no_from(capsys, reset_globals):
-    """Test _handlePacketFromRadio with no 'from' in the mesh packet."""
-    iface = MeshInterface(noProto=True)
-    meshPacket = mesh_pb2.MeshPacket()
-    iface._handlePacketFromRadio(meshPacket)
-    out, err = capsys.readouterr()
-    assert re.search(r'Device returned a packet we sent, ignoring', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_handlePacketFromRadio_no_portnum(caplog, reset_globals) -
-
-

Test _handlePacketFromRadio without a portnum

-
- -Expand source code - -
@pytest.mark.unit
-def test_handlePacketFromRadio_no_portnum(caplog, reset_globals):
-    """Test _handlePacketFromRadio without a portnum"""
-    iface = MeshInterface(noProto=True)
-    meshPacket = mesh_pb2.MeshPacket()
-    meshPacket.decoded.payload = b''
-    with caplog.at_level(logging.WARNING):
-        iface._handlePacketFromRadio(meshPacket, hack=True)
-    assert re.search(r'Not populating fromId', caplog.text, re.MULTILINE)
-
-
-
-def test_handlePacketFromRadio_with_a_portnum(caplog, reset_globals) -
-
-

Test _handlePacketFromRadio with a portnum -Since we have an attribute called 'from', we cannot simply 'set' it. -Had to implement a hack just to be able to test some code.

-
- -Expand source code - -
@pytest.mark.unit
-def test_handlePacketFromRadio_with_a_portnum(caplog, reset_globals):
-    """Test _handlePacketFromRadio with a portnum
-       Since we have an attribute called 'from', we cannot simply 'set' it.
-       Had to implement a hack just to be able to test some code.
-    """
-    iface = MeshInterface(noProto=True)
-    meshPacket = mesh_pb2.MeshPacket()
-    meshPacket.decoded.payload = b''
-    meshPacket.decoded.portnum = 1
-    with caplog.at_level(logging.WARNING):
-        iface._handlePacketFromRadio(meshPacket, hack=True)
-    assert re.search(r'Not populating fromId', caplog.text, re.MULTILINE)
-
-
-
-def test_sendData_too_long(caplog, reset_globals) -
-
-

Test when data payload is too big

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendData_too_long(caplog, reset_globals):
-    """Test when data payload is too big"""
-    iface = MeshInterface(noProto=True)
-    some_large_text = b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    some_large_text += b'This is a long text that will be too long for send text.'
-    with caplog.at_level(logging.DEBUG):
-        with pytest.raises(Exception) as pytest_wrapped_e:
-            iface.sendData(some_large_text)
-            assert re.search('Data payload too big', caplog.text, re.MULTILINE)
-        assert pytest_wrapped_e.type == Exception
-    iface.close()
-
-
-
-def test_sendData_unknown_app(capsys, reset_globals) -
-
-

Test sendData when unknown app

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendData_unknown_app(capsys, reset_globals):
-    """Test sendData when unknown app"""
-    iface = MeshInterface(noProto=True)
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        iface.sendData(b'hello', portNum=0)
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: A non-zero port number', out, re.MULTILINE)
-    assert err == ''
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-
-def test_sendPacket_with_destination_as_BROADCAST_ADDR(caplog, reset_globals) -
-
-

Test _sendPacket() with BROADCAST_ADDR as a destination

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPacket_with_destination_as_BROADCAST_ADDR(caplog, reset_globals):
-    """Test _sendPacket() with BROADCAST_ADDR as a destination"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId=BROADCAST_ADDR)
-        assert re.search(r'Not sending packet', caplog.text, re.MULTILINE)
-
-
-
-def test_sendPacket_with_destination_as_LOCAL_ADDR_no_myInfo(capsys, reset_globals) -
-
-

Test _sendPacket() with LOCAL_ADDR as a destination with no myInfo

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPacket_with_destination_as_LOCAL_ADDR_no_myInfo(capsys, reset_globals):
-    """Test _sendPacket() with LOCAL_ADDR as a destination with no myInfo"""
-    iface = MeshInterface(noProto=True)
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId=LOCAL_ADDR)
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: No myInfo', out, re.MULTILINE)
-    assert err == ''
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-
-def test_sendPacket_with_destination_as_LOCAL_ADDR_with_myInfo(caplog, reset_globals) -
-
-

Test _sendPacket() with LOCAL_ADDR as a destination with myInfo

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPacket_with_destination_as_LOCAL_ADDR_with_myInfo(caplog, reset_globals):
-    """Test _sendPacket() with LOCAL_ADDR as a destination with myInfo"""
-    iface = MeshInterface(noProto=True)
-    myInfo = MagicMock()
-    iface.myInfo = myInfo
-    with caplog.at_level(logging.DEBUG):
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId=LOCAL_ADDR)
-        assert re.search(r'Not sending packet', caplog.text, re.MULTILINE)
-
-
-
-def test_sendPacket_with_destination_as_int(caplog, reset_globals) -
-
-

Test _sendPacket() with int as a destination

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPacket_with_destination_as_int(caplog, reset_globals):
-    """Test _sendPacket() with int as a destination"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId=123)
-        assert re.search(r'Not sending packet', caplog.text, re.MULTILINE)
-
-
-
-def test_sendPacket_with_destination_is_blank_with_nodes(capsys, reset_globals, iface_with_nodes) -
-
-

Test _sendPacket() with '' as a destination with myInfo

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPacket_with_destination_is_blank_with_nodes(capsys, reset_globals, iface_with_nodes):
-    """Test _sendPacket() with '' as a destination with myInfo"""
-    iface = iface_with_nodes
-    meshPacket = mesh_pb2.MeshPacket()
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        iface._sendPacket(meshPacket, destinationId='')
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.match(r'Warning: NodeId  not found in DB', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_sendPacket_with_destination_is_blank_without_nodes(caplog, reset_globals, iface_with_nodes) -
-
-

Test _sendPacket() with '' as a destination with myInfo

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPacket_with_destination_is_blank_without_nodes(caplog, reset_globals, iface_with_nodes):
-    """Test _sendPacket() with '' as a destination with myInfo"""
-    iface = iface_with_nodes
-    iface.nodes = None
-    meshPacket = mesh_pb2.MeshPacket()
-    with caplog.at_level(logging.WARNING):
-        iface._sendPacket(meshPacket, destinationId='')
-    assert re.search(r'Warning: There were no self.nodes.', caplog.text, re.MULTILINE)
-
-
-
-def test_sendPacket_with_destination_starting_with_a_bang(caplog, reset_globals) -
-
-

Test _sendPacket() with int as a destination

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPacket_with_destination_starting_with_a_bang(caplog, reset_globals):
-    """Test _sendPacket() with int as a destination"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        meshPacket = mesh_pb2.MeshPacket()
-        iface._sendPacket(meshPacket, destinationId='!1234')
-        assert re.search(r'Not sending packet', caplog.text, re.MULTILINE)
-
-
-
-def test_sendPacket_with_no_destination(capsys, reset_globals) -
-
-

Test _sendPacket()

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPacket_with_no_destination(capsys, reset_globals):
-    """Test _sendPacket()"""
-    iface = MeshInterface(noProto=True)
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        iface._sendPacket(b'', destinationId=None)
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: destinationId must not be None', out, re.MULTILINE)
-    assert err == ''
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-
-def test_sendPosition(reset_globals, caplog) -
-
-

Test sendPosition

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPosition(reset_globals, caplog):
-    """Test sendPosition"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface.sendPosition()
-    iface.close()
-    assert re.search(r'p.time:', caplog.text, re.MULTILINE)
-
-
-
-def test_sendPosition_with_a_position(caplog, reset_globals) -
-
-

Test sendPosition when lat/long/alt

-
- -Expand source code - -
@pytest.mark.unit
-def test_sendPosition_with_a_position(caplog, reset_globals):
-    """Test sendPosition when lat/long/alt"""
-    iface = MeshInterface(noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        iface.sendPosition(latitude=40.8, longitude=-111.86, altitude=201)
-        assert re.search(r'p.latitude_i:408', caplog.text, re.MULTILINE)
-        assert re.search(r'p.longitude_i:-11186', caplog.text, re.MULTILINE)
-        assert re.search(r'p.altitude:201', caplog.text, re.MULTILINE)
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_node.html b/docs/meshtastic/tests/test_node.html deleted file mode 100644 index e5196ed..0000000 --- a/docs/meshtastic/tests/test_node.html +++ /dev/null @@ -1,4143 +0,0 @@ - - - - - - -meshtastic.tests.test_node API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_node

-
-
-

Meshtastic unit tests for node.py

-
- -Expand source code - -
"""Meshtastic unit tests for node.py"""
-
-import re
-import logging
-
-from unittest.mock import patch, MagicMock
-import pytest
-
-from ..node import Node
-from ..serial_interface import SerialInterface
-from ..admin_pb2 import AdminMessage
-from ..channel_pb2 import Channel
-from ..radioconfig_pb2 import RadioConfig
-
-
-@pytest.mark.unit
-def test_node(capsys):
-    """Test that we can instantiate a Node"""
-    anode = Node('foo', 'bar')
-    radioConfig = RadioConfig()
-    anode.radioConfig = radioConfig
-    anode.showChannels()
-    anode.showInfo()
-    out, err = capsys.readouterr()
-    assert re.search(r'Preferences', out)
-    assert re.search(r'Channels', out)
-    assert re.search(r'Primary channel URL', out)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_node_reqquestConfig():
-    """Test run requestConfig"""
-    iface = MagicMock(autospec=SerialInterface)
-    amesg = MagicMock(autospec=AdminMessage)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with patch('meshtastic.admin_pb2.AdminMessage', return_value=amesg):
-            anode = Node(mo, 'bar')
-            anode.requestConfig()
-
-
-@pytest.mark.unit
-def test_setOwner_and_team(caplog):
-    """Test setOwner"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.setOwner(long_name ='Test123', short_name='123', team=1)
-    assert re.search(r'p.set_owner.long_name:Test123:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.short_name:123:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.is_licensed:False', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.team:1', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_setOwner_no_short_name(caplog):
-    """Test setOwner"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.setOwner(long_name ='Test123')
-    assert re.search(r'p.set_owner.long_name:Test123:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.short_name:Tst:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.is_licensed:False', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.team:0', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_setOwner_no_short_name_and_long_name_is_short(caplog):
-    """Test setOwner"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.setOwner(long_name ='Tnt')
-    assert re.search(r'p.set_owner.long_name:Tnt:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.short_name:Tnt:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.is_licensed:False', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.team:0', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_setOwner_no_short_name_and_long_name_has_words(caplog):
-    """Test setOwner"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.setOwner(long_name ='A B C', is_licensed=True)
-    assert re.search(r'p.set_owner.long_name:A B C:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.short_name:ABC:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.is_licensed:True', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.team:0', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_exitSimulator(caplog):
-    """Test exitSimulator"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.exitSimulator()
-    assert re.search(r'in exitSimulator', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_reboot(caplog):
-    """Test reboot"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.reboot()
-    assert re.search(r'Telling node to reboot', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_setURL_empty_url():
-    """Test reboot"""
-    anode = Node('foo', 'bar', noProto=True)
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        anode.setURL('')
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-@pytest.mark.unit
-def test_setURL_valid_URL(caplog):
-    """Test setURL"""
-    iface = MagicMock(autospec=SerialInterface)
-    url = "https://www.meshtastic.org/d/#CgUYAyIBAQ"
-    with caplog.at_level(logging.DEBUG):
-        anode = Node(iface, 'bar', noProto=True)
-        anode.radioConfig = 'baz'
-        channels = ['zoo']
-        anode.channels = channels
-        anode.setURL(url)
-    assert re.search(r'Channel i:0', caplog.text, re.MULTILINE)
-    assert re.search(r'modem_config: Bw125Cr48Sf4096', caplog.text, re.MULTILINE)
-    assert re.search(r'psk: "\\001"', caplog.text, re.MULTILINE)
-    assert re.search(r'role: PRIMARY', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_setURL_valid_URL_but_no_settings(caplog):
-    """Test setURL"""
-    iface = MagicMock(autospec=SerialInterface)
-    url = "https://www.meshtastic.org/d/#"
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        anode = Node(iface, 'bar', noProto=True)
-        anode.radioConfig = 'baz'
-        anode.setURL(url)
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-@pytest.mark.unit
-def test_showChannels(capsys):
-    """Test showChannels"""
-    anode = Node('foo', 'bar')
-
-    # primary channel
-    # role: 0=Disabled, 1=Primary, 2=Secondary
-    # modem_config: 0-5
-    # role: 0=Disabled, 1=Primary, 2=Secondary
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'testing'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    anode.showChannels()
-    out, err = capsys.readouterr()
-    assert re.search(r'Channels:', out, re.MULTILINE)
-    # primary channel
-    assert re.search(r'Primary channel URL', out, re.MULTILINE)
-    assert re.search(r'PRIMARY psk=default ', out, re.MULTILINE)
-    assert re.search(r'"modemConfig": "Bw125Cr48Sf4096"', out, re.MULTILINE)
-    assert re.search(r'"psk": "AQ=="', out, re.MULTILINE)
-    # secondary channel
-    assert re.search(r'SECONDARY psk=secret ', out, re.MULTILINE)
-    assert re.search(r'"psk": "ipR5DsbJHjWREkCmMKi0M4cA8ksO539Bes31sJAwqDQ="', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_getChannelByChannelIndex():
-    """Test getChannelByChannelIndex()"""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1) # primary channel
-    channel2 = Channel(index=2, role=2) # secondary channel
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-
-    # test primary
-    assert anode.getChannelByChannelIndex(0) is not None
-    # test secondary
-    assert anode.getChannelByChannelIndex(1) is not None
-    # test disabled
-    assert anode.getChannelByChannelIndex(2) is not None
-    # test invalid values
-    assert anode.getChannelByChannelIndex(-1) is None
-    assert anode.getChannelByChannelIndex(9) is None
-
-
-@pytest.mark.unit
-def test_deleteChannel_try_to_delete_primary_channel(capsys):
-    """Try to delete primary channel."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    # no secondary channels
-    channel2 = Channel(index=2, role=0)
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        anode.deleteChannel(0)
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: Only SECONDARY channels can be deleted', out, re.MULTILINE)
-    assert err == ''
-
-@pytest.mark.unit
-def test_deleteChannel_secondary():
-    """Try to delete a secondary channel."""
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'testing'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        anode.channels = channels
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'testing'
-        assert channels[2].settings.name == ''
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-        anode.deleteChannel(1)
-
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == ''
-        assert channels[2].settings.name == ''
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-
-@pytest.mark.unit
-def test_deleteChannel_secondary_with_admin_channel_after_testing():
-    """Try to delete a secondary channel where there is an admin channel."""
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'testing'
-
-    channel3 = Channel(index=3, role=2)
-    channel3.settings.name = 'admin'
-
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        assert mo.localNode == anode
-
-        anode.channels = channels
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'testing'
-        assert channels[2].settings.name == 'admin'
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-        anode.deleteChannel(1)
-
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'admin'
-        assert channels[2].settings.name == ''
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-
-@pytest.mark.unit
-def test_deleteChannel_secondary_with_admin_channel_before_testing():
-    """Try to delete a secondary channel where there is an admin channel."""
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'admin'
-
-    channel3 = Channel(index=3, role=2)
-    channel3.settings.name = 'testing'
-
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        anode.channels = channels
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'admin'
-        assert channels[2].settings.name == 'testing'
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-        anode.deleteChannel(2)
-
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'admin'
-        assert channels[2].settings.name == ''
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-
-@pytest.mark.unit
-def test_getChannelByName(capsys):
-    """Get a channel by the name."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'admin'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    ch = anode.getChannelByName('admin')
-    assert ch.index == 2
-
-
-@pytest.mark.unit
-def test_getChannelByName_invalid_name(capsys):
-    """Get a channel by the name but one that is not present."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'admin'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    ch = anode.getChannelByName('testing')
-    assert ch is None
-
-
-@pytest.mark.unit
-def test_getDisabledChannel(capsys):
-    """Get the first disabled channel."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'testingA'
-
-    channel3 = Channel(index=3, role=2)
-    channel3.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel3.settings.name = 'testingB'
-
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    ch = anode.getDisabledChannel()
-    assert ch.index == 4
-
-
-@pytest.mark.unit
-def test_getDisabledChannel_where_all_channels_are_used(capsys):
-    """Get the first disabled channel."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel3 = Channel(index=3, role=2)
-    channel4 = Channel(index=4, role=2)
-    channel5 = Channel(index=5, role=2)
-    channel6 = Channel(index=6, role=2)
-    channel7 = Channel(index=7, role=2)
-    channel8 = Channel(index=8, role=2)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    ch = anode.getDisabledChannel()
-    assert ch is None
-
-
-@pytest.mark.unit
-def test_getAdminChannelIndex(capsys):
-    """Get the 'admin' channel index."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'admin'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    i = anode._getAdminChannelIndex()
-    assert i == 2
-
-
-@pytest.mark.unit
-def test_getAdminChannelIndex_when_no_admin_named_channel(capsys):
-    """Get the 'admin' channel when there is not one."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=0)
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    i = anode._getAdminChannelIndex()
-    assert i == 0
-
-
-# TODO: should we check if we need to turn it off?
-@pytest.mark.unit
-def test_turnOffEncryptionOnPrimaryChannel(capsys):
-    """Turn off encryption when there is a psk."""
-    anode = Node('foo', 'bar', noProto=True)
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    # value from using "--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b "
-    channel1.settings.psk = b'\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++'
-
-    channel2 = Channel(index=2, role=0)
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    anode.turnOffEncryptionOnPrimaryChannel()
-    out, err = capsys.readouterr()
-    assert re.search(r'Writing modified channels to device', out)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_writeConfig_with_no_radioConfig(capsys):
-    """Test writeConfig with no radioConfig."""
-    anode = Node('foo', 'bar', noProto=True)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        anode.writeConfig()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Error: No RadioConfig has been read', out)
-    assert err == ''
-
-
-@pytest.mark.unit
-def test_writeConfig(caplog):
-    """Test writeConfig"""
-    anode = Node('foo', 'bar', noProto=True)
-    radioConfig = RadioConfig()
-    anode.radioConfig = radioConfig
-
-    with caplog.at_level(logging.DEBUG):
-        anode.writeConfig()
-    assert re.search(r'Wrote config', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_requestChannel_not_localNode(caplog):
-    """Test _requestChannel()"""
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-        with caplog.at_level(logging.DEBUG):
-            anode._requestChannel(0)
-            assert re.search(r'Requesting channel 0 info from remote node', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_requestChannel_localNode(caplog):
-    """Test _requestChannel()"""
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        with caplog.at_level(logging.DEBUG):
-            anode._requestChannel(0)
-            assert re.search(r'Requesting channel 0', caplog.text, re.MULTILINE)
-            assert not re.search(r'from remote node', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_onResponseRequestChannel(caplog):
-    """Test onResponseRequestChannel()"""
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    msg1 = MagicMock(autospec=AdminMessage)
-    msg1.get_channel_response = channel1
-
-    msg2 = MagicMock(autospec=AdminMessage)
-    channel2 = Channel(index=2, role=0) # disabled
-    msg2.get_channel_response = channel2
-
-    # default primary channel
-    packet1 = {
-        'from': 2475227164,
-        'to': 2475227164,
-        'decoded': {
-            'portnum': 'ADMIN_APP',
-            'payload': b':\t\x12\x05\x18\x03"\x01\x01\x18\x01',
-            'requestId': 2615094405,
-            'admin': {
-                'getChannelResponse': {
-                    'settings': {
-                        'modemConfig': 'Bw125Cr48Sf4096',
-                        'psk': 'AQ=='
-                    },
-                    'role': 'PRIMARY'
-                },
-                'raw': msg1,
-            }
-        },
-        'id': 1692918436,
-        'hopLimit': 3,
-        'priority':
-        'RELIABLE',
-        'raw': 'fake',
-        'fromId': '!9388f81c',
-        'toId': '!9388f81c'
-        }
-
-    # no other channels
-    packet2 = {
-        'from': 2475227164,
-        'to': 2475227164,
-        'decoded': {
-            'portnum': 'ADMIN_APP',
-            'payload': b':\x04\x08\x02\x12\x00',
-            'requestId': 743049663,
-            'admin': {
-                'getChannelResponse': {
-                    'index': 2,
-                    'settings': {}
-                },
-                'raw': msg2,
-            }
-        },
-        'id': 1692918456,
-        'rxTime': 1640202239,
-        'hopLimit': 3,
-        'priority': 'RELIABLE',
-        'raw': 'faked',
-        'fromId': '!9388f81c',
-        'toId': '!9388f81c'
-    }
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        radioConfig = RadioConfig()
-        anode.radioConfig = radioConfig
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        with caplog.at_level(logging.DEBUG):
-            anode.requestConfig()
-            anode.onResponseRequestChannel(packet1)
-            assert re.search(r'Received channel', caplog.text, re.MULTILINE)
-            anode.onResponseRequestChannel(packet2)
-            assert re.search(r'Received channel', caplog.text, re.MULTILINE)
-            assert re.search(r'Finished downloading channels', caplog.text, re.MULTILINE)
-            assert len(anode.channels) == 8
-            assert anode.channels[0].settings.modem_config == 3
-            assert anode.channels[1].settings.name == ''
-            assert anode.channels[2].settings.name == ''
-            assert anode.channels[3].settings.name == ''
-            assert anode.channels[4].settings.name == ''
-            assert anode.channels[5].settings.name == ''
-            assert anode.channels[6].settings.name == ''
-            assert anode.channels[7].settings.name == ''
-
-
-@pytest.mark.unit
-def test_onResponseRequestSetting(caplog):
-    """Test onResponseRequestSetting()"""
-    # Note: Split out the get_radio_response to a MagicMock
-    # so it could be "returned" (not really sure how to do that
-    # in a python dict.
-    amsg = MagicMock(autospec=AdminMessage)
-    amsg.get_radio_response = """{
-  preferences {
-    phone_timeout_secs: 900
-    ls_secs: 300
-    position_broadcast_smart: true
-    position_flags: 35
-  }
-}"""
-    packet = {
-        'from': 2475227164,
-        'to': 2475227164,
-        'decoded': {
-            'portnum': 'ADMIN_APP',
-            'payload': b'*\x0e\n\x0c0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#',
-            'requestId': 3145147848,
-            'admin': {
-                'getRadioResponse': {
-                    'preferences': {
-                        'phoneTimeoutSecs': 900,
-                        'lsSecs': 300,
-                        'positionBroadcastSmart': True,
-                        'positionFlags': 35
-                     }
-                },
-                'raw': amsg
-            },
-            'id': 365963704,
-            'rxTime': 1640195197,
-            'hopLimit': 3,
-            'priority': 'RELIABLE',
-            'raw': 'faked',
-            'fromId': '!9388f81c',
-            'toId': '!9388f81c'
-        }
-    }
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        radioConfig = RadioConfig()
-        anode.radioConfig = radioConfig
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        with caplog.at_level(logging.DEBUG):
-            anode.onResponseRequestSettings(packet)
-            assert re.search(r'Received radio config, now fetching channels..', caplog.text, re.MULTILINE)
-
-
-@pytest.mark.unit
-def test_onResponseRequestSetting_with_error(capsys):
-    """Test onResponseRequestSetting() with an error"""
-    packet = {
-        'from': 2475227164,
-        'to': 2475227164,
-        'decoded': {
-            'portnum': 'ADMIN_APP',
-            'payload': b'*\x0e\n\x0c0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#',
-            'requestId': 3145147848,
-            'routing': {
-                'errorReason': 'some made up error',
-            },
-            'admin': {
-                'getRadioResponse': {
-                    'preferences': {
-                        'phoneTimeoutSecs': 900,
-                        'lsSecs': 300,
-                        'positionBroadcastSmart': True,
-                        'positionFlags': 35
-                     }
-                },
-            },
-            'id': 365963704,
-            'rxTime': 1640195197,
-            'hopLimit': 3,
-            'priority': 'RELIABLE',
-            'fromId': '!9388f81c',
-            'toId': '!9388f81c'
-        }
-    }
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        radioConfig = RadioConfig()
-        anode.radioConfig = radioConfig
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        anode.onResponseRequestSettings(packet)
-        out, err = capsys.readouterr()
-        assert re.search(r'Error on response', out)
-        assert err == ''
-
-
-
-
-
-
-
-

Functions

-
-
-def test_deleteChannel_secondary() -
-
-

Try to delete a secondary channel.

-
- -Expand source code - -
@pytest.mark.unit
-def test_deleteChannel_secondary():
-    """Try to delete a secondary channel."""
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'testing'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        anode.channels = channels
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'testing'
-        assert channels[2].settings.name == ''
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-        anode.deleteChannel(1)
-
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == ''
-        assert channels[2].settings.name == ''
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-
-
-def test_deleteChannel_secondary_with_admin_channel_after_testing() -
-
-

Try to delete a secondary channel where there is an admin channel.

-
- -Expand source code - -
@pytest.mark.unit
-def test_deleteChannel_secondary_with_admin_channel_after_testing():
-    """Try to delete a secondary channel where there is an admin channel."""
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'testing'
-
-    channel3 = Channel(index=3, role=2)
-    channel3.settings.name = 'admin'
-
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        assert mo.localNode == anode
-
-        anode.channels = channels
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'testing'
-        assert channels[2].settings.name == 'admin'
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-        anode.deleteChannel(1)
-
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'admin'
-        assert channels[2].settings.name == ''
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-
-
-def test_deleteChannel_secondary_with_admin_channel_before_testing() -
-
-

Try to delete a secondary channel where there is an admin channel.

-
- -Expand source code - -
@pytest.mark.unit
-def test_deleteChannel_secondary_with_admin_channel_before_testing():
-    """Try to delete a secondary channel where there is an admin channel."""
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'admin'
-
-    channel3 = Channel(index=3, role=2)
-    channel3.settings.name = 'testing'
-
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        anode.channels = channels
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'admin'
-        assert channels[2].settings.name == 'testing'
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-        anode.deleteChannel(2)
-
-        assert len(anode.channels) == 8
-        assert channels[0].settings.modem_config == 3
-        assert channels[1].settings.name == 'admin'
-        assert channels[2].settings.name == ''
-        assert channels[3].settings.name == ''
-        assert channels[4].settings.name == ''
-        assert channels[5].settings.name == ''
-        assert channels[6].settings.name == ''
-        assert channels[7].settings.name == ''
-
-
-
-def test_deleteChannel_try_to_delete_primary_channel(capsys) -
-
-

Try to delete primary channel.

-
- -Expand source code - -
@pytest.mark.unit
-def test_deleteChannel_try_to_delete_primary_channel(capsys):
-    """Try to delete primary channel."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    # no secondary channels
-    channel2 = Channel(index=2, role=0)
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        anode.deleteChannel(0)
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: Only SECONDARY channels can be deleted', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_exitSimulator(caplog) -
-
-

Test exitSimulator

-
- -Expand source code - -
@pytest.mark.unit
-def test_exitSimulator(caplog):
-    """Test exitSimulator"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.exitSimulator()
-    assert re.search(r'in exitSimulator', caplog.text, re.MULTILINE)
-
-
-
-def test_getAdminChannelIndex(capsys) -
-
-

Get the 'admin' channel index.

-
- -Expand source code - -
@pytest.mark.unit
-def test_getAdminChannelIndex(capsys):
-    """Get the 'admin' channel index."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'admin'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    i = anode._getAdminChannelIndex()
-    assert i == 2
-
-
-
-def test_getAdminChannelIndex_when_no_admin_named_channel(capsys) -
-
-

Get the 'admin' channel when there is not one.

-
- -Expand source code - -
@pytest.mark.unit
-def test_getAdminChannelIndex_when_no_admin_named_channel(capsys):
-    """Get the 'admin' channel when there is not one."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=0)
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    i = anode._getAdminChannelIndex()
-    assert i == 0
-
-
-
-def test_getChannelByChannelIndex() -
-
-

Test getChannelByChannelIndex()

-
- -Expand source code - -
@pytest.mark.unit
-def test_getChannelByChannelIndex():
-    """Test getChannelByChannelIndex()"""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1) # primary channel
-    channel2 = Channel(index=2, role=2) # secondary channel
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-
-    # test primary
-    assert anode.getChannelByChannelIndex(0) is not None
-    # test secondary
-    assert anode.getChannelByChannelIndex(1) is not None
-    # test disabled
-    assert anode.getChannelByChannelIndex(2) is not None
-    # test invalid values
-    assert anode.getChannelByChannelIndex(-1) is None
-    assert anode.getChannelByChannelIndex(9) is None
-
-
-
-def test_getChannelByName(capsys) -
-
-

Get a channel by the name.

-
- -Expand source code - -
@pytest.mark.unit
-def test_getChannelByName(capsys):
-    """Get a channel by the name."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'admin'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    ch = anode.getChannelByName('admin')
-    assert ch.index == 2
-
-
-
-def test_getChannelByName_invalid_name(capsys) -
-
-

Get a channel by the name but one that is not present.

-
- -Expand source code - -
@pytest.mark.unit
-def test_getChannelByName_invalid_name(capsys):
-    """Get a channel by the name but one that is not present."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'admin'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    ch = anode.getChannelByName('testing')
-    assert ch is None
-
-
-
-def test_getDisabledChannel(capsys) -
-
-

Get the first disabled channel.

-
- -Expand source code - -
@pytest.mark.unit
-def test_getDisabledChannel(capsys):
-    """Get the first disabled channel."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'testingA'
-
-    channel3 = Channel(index=3, role=2)
-    channel3.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel3.settings.name = 'testingB'
-
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    ch = anode.getDisabledChannel()
-    assert ch.index == 4
-
-
-
-def test_getDisabledChannel_where_all_channels_are_used(capsys) -
-
-

Get the first disabled channel.

-
- -Expand source code - -
@pytest.mark.unit
-def test_getDisabledChannel_where_all_channels_are_used(capsys):
-    """Get the first disabled channel."""
-    anode = Node('foo', 'bar')
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel3 = Channel(index=3, role=2)
-    channel4 = Channel(index=4, role=2)
-    channel5 = Channel(index=5, role=2)
-    channel6 = Channel(index=6, role=2)
-    channel7 = Channel(index=7, role=2)
-    channel8 = Channel(index=8, role=2)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    ch = anode.getDisabledChannel()
-    assert ch is None
-
-
-
-def test_node(capsys) -
-
-

Test that we can instantiate a Node

-
- -Expand source code - -
@pytest.mark.unit
-def test_node(capsys):
-    """Test that we can instantiate a Node"""
-    anode = Node('foo', 'bar')
-    radioConfig = RadioConfig()
-    anode.radioConfig = radioConfig
-    anode.showChannels()
-    anode.showInfo()
-    out, err = capsys.readouterr()
-    assert re.search(r'Preferences', out)
-    assert re.search(r'Channels', out)
-    assert re.search(r'Primary channel URL', out)
-    assert err == ''
-
-
-
-def test_node_reqquestConfig() -
-
-

Test run requestConfig

-
- -Expand source code - -
@pytest.mark.unit
-def test_node_reqquestConfig():
-    """Test run requestConfig"""
-    iface = MagicMock(autospec=SerialInterface)
-    amesg = MagicMock(autospec=AdminMessage)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        with patch('meshtastic.admin_pb2.AdminMessage', return_value=amesg):
-            anode = Node(mo, 'bar')
-            anode.requestConfig()
-
-
-
-def test_onResponseRequestChannel(caplog) -
-
-

Test onResponseRequestChannel()

-
- -Expand source code - -
@pytest.mark.unit
-def test_onResponseRequestChannel(caplog):
-    """Test onResponseRequestChannel()"""
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    msg1 = MagicMock(autospec=AdminMessage)
-    msg1.get_channel_response = channel1
-
-    msg2 = MagicMock(autospec=AdminMessage)
-    channel2 = Channel(index=2, role=0) # disabled
-    msg2.get_channel_response = channel2
-
-    # default primary channel
-    packet1 = {
-        'from': 2475227164,
-        'to': 2475227164,
-        'decoded': {
-            'portnum': 'ADMIN_APP',
-            'payload': b':\t\x12\x05\x18\x03"\x01\x01\x18\x01',
-            'requestId': 2615094405,
-            'admin': {
-                'getChannelResponse': {
-                    'settings': {
-                        'modemConfig': 'Bw125Cr48Sf4096',
-                        'psk': 'AQ=='
-                    },
-                    'role': 'PRIMARY'
-                },
-                'raw': msg1,
-            }
-        },
-        'id': 1692918436,
-        'hopLimit': 3,
-        'priority':
-        'RELIABLE',
-        'raw': 'fake',
-        'fromId': '!9388f81c',
-        'toId': '!9388f81c'
-        }
-
-    # no other channels
-    packet2 = {
-        'from': 2475227164,
-        'to': 2475227164,
-        'decoded': {
-            'portnum': 'ADMIN_APP',
-            'payload': b':\x04\x08\x02\x12\x00',
-            'requestId': 743049663,
-            'admin': {
-                'getChannelResponse': {
-                    'index': 2,
-                    'settings': {}
-                },
-                'raw': msg2,
-            }
-        },
-        'id': 1692918456,
-        'rxTime': 1640202239,
-        'hopLimit': 3,
-        'priority': 'RELIABLE',
-        'raw': 'faked',
-        'fromId': '!9388f81c',
-        'toId': '!9388f81c'
-    }
-
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        radioConfig = RadioConfig()
-        anode.radioConfig = radioConfig
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        with caplog.at_level(logging.DEBUG):
-            anode.requestConfig()
-            anode.onResponseRequestChannel(packet1)
-            assert re.search(r'Received channel', caplog.text, re.MULTILINE)
-            anode.onResponseRequestChannel(packet2)
-            assert re.search(r'Received channel', caplog.text, re.MULTILINE)
-            assert re.search(r'Finished downloading channels', caplog.text, re.MULTILINE)
-            assert len(anode.channels) == 8
-            assert anode.channels[0].settings.modem_config == 3
-            assert anode.channels[1].settings.name == ''
-            assert anode.channels[2].settings.name == ''
-            assert anode.channels[3].settings.name == ''
-            assert anode.channels[4].settings.name == ''
-            assert anode.channels[5].settings.name == ''
-            assert anode.channels[6].settings.name == ''
-            assert anode.channels[7].settings.name == ''
-
-
-
-def test_onResponseRequestSetting(caplog) -
-
-

Test onResponseRequestSetting()

-
- -Expand source code - -
@pytest.mark.unit
-def test_onResponseRequestSetting(caplog):
-    """Test onResponseRequestSetting()"""
-    # Note: Split out the get_radio_response to a MagicMock
-    # so it could be "returned" (not really sure how to do that
-    # in a python dict.
-    amsg = MagicMock(autospec=AdminMessage)
-    amsg.get_radio_response = """{
-  preferences {
-    phone_timeout_secs: 900
-    ls_secs: 300
-    position_broadcast_smart: true
-    position_flags: 35
-  }
-}"""
-    packet = {
-        'from': 2475227164,
-        'to': 2475227164,
-        'decoded': {
-            'portnum': 'ADMIN_APP',
-            'payload': b'*\x0e\n\x0c0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#',
-            'requestId': 3145147848,
-            'admin': {
-                'getRadioResponse': {
-                    'preferences': {
-                        'phoneTimeoutSecs': 900,
-                        'lsSecs': 300,
-                        'positionBroadcastSmart': True,
-                        'positionFlags': 35
-                     }
-                },
-                'raw': amsg
-            },
-            'id': 365963704,
-            'rxTime': 1640195197,
-            'hopLimit': 3,
-            'priority': 'RELIABLE',
-            'raw': 'faked',
-            'fromId': '!9388f81c',
-            'toId': '!9388f81c'
-        }
-    }
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        radioConfig = RadioConfig()
-        anode.radioConfig = radioConfig
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        with caplog.at_level(logging.DEBUG):
-            anode.onResponseRequestSettings(packet)
-            assert re.search(r'Received radio config, now fetching channels..', caplog.text, re.MULTILINE)
-
-
-
-def test_onResponseRequestSetting_with_error(capsys) -
-
-

Test onResponseRequestSetting() with an error

-
- -Expand source code - -
@pytest.mark.unit
-def test_onResponseRequestSetting_with_error(capsys):
-    """Test onResponseRequestSetting() with an error"""
-    packet = {
-        'from': 2475227164,
-        'to': 2475227164,
-        'decoded': {
-            'portnum': 'ADMIN_APP',
-            'payload': b'*\x0e\n\x0c0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#',
-            'requestId': 3145147848,
-            'routing': {
-                'errorReason': 'some made up error',
-            },
-            'admin': {
-                'getRadioResponse': {
-                    'preferences': {
-                        'phoneTimeoutSecs': 900,
-                        'lsSecs': 300,
-                        'positionBroadcastSmart': True,
-                        'positionFlags': 35
-                     }
-                },
-            },
-            'id': 365963704,
-            'rxTime': 1640195197,
-            'hopLimit': 3,
-            'priority': 'RELIABLE',
-            'fromId': '!9388f81c',
-            'toId': '!9388f81c'
-        }
-    }
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        radioConfig = RadioConfig()
-        anode.radioConfig = radioConfig
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        anode.onResponseRequestSettings(packet)
-        out, err = capsys.readouterr()
-        assert re.search(r'Error on response', out)
-        assert err == ''
-
-
-
-def test_reboot(caplog) -
-
-

Test reboot

-
- -Expand source code - -
@pytest.mark.unit
-def test_reboot(caplog):
-    """Test reboot"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.reboot()
-    assert re.search(r'Telling node to reboot', caplog.text, re.MULTILINE)
-
-
-
-def test_requestChannel_localNode(caplog) -
-
-

Test _requestChannel()

-
- -Expand source code - -
@pytest.mark.unit
-def test_requestChannel_localNode(caplog):
-    """Test _requestChannel()"""
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-
-        # Note: Have to do this next line because every call to MagicMock object/method returns a new magic mock
-        mo.localNode = anode
-
-        with caplog.at_level(logging.DEBUG):
-            anode._requestChannel(0)
-            assert re.search(r'Requesting channel 0', caplog.text, re.MULTILINE)
-            assert not re.search(r'from remote node', caplog.text, re.MULTILINE)
-
-
-
-def test_requestChannel_not_localNode(caplog) -
-
-

Test _requestChannel()

-
- -Expand source code - -
@pytest.mark.unit
-def test_requestChannel_not_localNode(caplog):
-    """Test _requestChannel()"""
-    iface = MagicMock(autospec=SerialInterface)
-    with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
-        mo.localNode.getChannelByName.return_value = None
-        mo.myInfo.max_channels = 8
-        anode = Node(mo, 'bar', noProto=True)
-        with caplog.at_level(logging.DEBUG):
-            anode._requestChannel(0)
-            assert re.search(r'Requesting channel 0 info from remote node', caplog.text, re.MULTILINE)
-
-
-
-def test_setOwner_and_team(caplog) -
-
-

Test setOwner

-
- -Expand source code - -
@pytest.mark.unit
-def test_setOwner_and_team(caplog):
-    """Test setOwner"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.setOwner(long_name ='Test123', short_name='123', team=1)
-    assert re.search(r'p.set_owner.long_name:Test123:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.short_name:123:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.is_licensed:False', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.team:1', caplog.text, re.MULTILINE)
-
-
-
-def test_setOwner_no_short_name(caplog) -
-
-

Test setOwner

-
- -Expand source code - -
@pytest.mark.unit
-def test_setOwner_no_short_name(caplog):
-    """Test setOwner"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.setOwner(long_name ='Test123')
-    assert re.search(r'p.set_owner.long_name:Test123:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.short_name:Tst:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.is_licensed:False', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.team:0', caplog.text, re.MULTILINE)
-
-
-
-def test_setOwner_no_short_name_and_long_name_has_words(caplog) -
-
-

Test setOwner

-
- -Expand source code - -
@pytest.mark.unit
-def test_setOwner_no_short_name_and_long_name_has_words(caplog):
-    """Test setOwner"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.setOwner(long_name ='A B C', is_licensed=True)
-    assert re.search(r'p.set_owner.long_name:A B C:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.short_name:ABC:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.is_licensed:True', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.team:0', caplog.text, re.MULTILINE)
-
-
-
-def test_setOwner_no_short_name_and_long_name_is_short(caplog) -
-
-

Test setOwner

-
- -Expand source code - -
@pytest.mark.unit
-def test_setOwner_no_short_name_and_long_name_is_short(caplog):
-    """Test setOwner"""
-    anode = Node('foo', 'bar', noProto=True)
-    with caplog.at_level(logging.DEBUG):
-        anode.setOwner(long_name ='Tnt')
-    assert re.search(r'p.set_owner.long_name:Tnt:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.short_name:Tnt:', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.is_licensed:False', caplog.text, re.MULTILINE)
-    assert re.search(r'p.set_owner.team:0', caplog.text, re.MULTILINE)
-
-
-
-def test_setURL_empty_url() -
-
-

Test reboot

-
- -Expand source code - -
@pytest.mark.unit
-def test_setURL_empty_url():
-    """Test reboot"""
-    anode = Node('foo', 'bar', noProto=True)
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        anode.setURL('')
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-
-def test_setURL_valid_URL(caplog) -
-
-

Test setURL

-
- -Expand source code - -
@pytest.mark.unit
-def test_setURL_valid_URL(caplog):
-    """Test setURL"""
-    iface = MagicMock(autospec=SerialInterface)
-    url = "https://www.meshtastic.org/d/#CgUYAyIBAQ"
-    with caplog.at_level(logging.DEBUG):
-        anode = Node(iface, 'bar', noProto=True)
-        anode.radioConfig = 'baz'
-        channels = ['zoo']
-        anode.channels = channels
-        anode.setURL(url)
-    assert re.search(r'Channel i:0', caplog.text, re.MULTILINE)
-    assert re.search(r'modem_config: Bw125Cr48Sf4096', caplog.text, re.MULTILINE)
-    assert re.search(r'psk: "\\001"', caplog.text, re.MULTILINE)
-    assert re.search(r'role: PRIMARY', caplog.text, re.MULTILINE)
-
-
-
-def test_setURL_valid_URL_but_no_settings(caplog) -
-
-

Test setURL

-
- -Expand source code - -
@pytest.mark.unit
-def test_setURL_valid_URL_but_no_settings(caplog):
-    """Test setURL"""
-    iface = MagicMock(autospec=SerialInterface)
-    url = "https://www.meshtastic.org/d/#"
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        anode = Node(iface, 'bar', noProto=True)
-        anode.radioConfig = 'baz'
-        anode.setURL(url)
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-
-def test_showChannels(capsys) -
-
-

Test showChannels

-
- -Expand source code - -
@pytest.mark.unit
-def test_showChannels(capsys):
-    """Test showChannels"""
-    anode = Node('foo', 'bar')
-
-    # primary channel
-    # role: 0=Disabled, 1=Primary, 2=Secondary
-    # modem_config: 0-5
-    # role: 0=Disabled, 1=Primary, 2=Secondary
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    channel1.settings.psk = b'\x01'
-
-    channel2 = Channel(index=2, role=2)
-    channel2.settings.psk = b'\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84'
-    channel2.settings.name = 'testing'
-
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    anode.showChannels()
-    out, err = capsys.readouterr()
-    assert re.search(r'Channels:', out, re.MULTILINE)
-    # primary channel
-    assert re.search(r'Primary channel URL', out, re.MULTILINE)
-    assert re.search(r'PRIMARY psk=default ', out, re.MULTILINE)
-    assert re.search(r'"modemConfig": "Bw125Cr48Sf4096"', out, re.MULTILINE)
-    assert re.search(r'"psk": "AQ=="', out, re.MULTILINE)
-    # secondary channel
-    assert re.search(r'SECONDARY psk=secret ', out, re.MULTILINE)
-    assert re.search(r'"psk": "ipR5DsbJHjWREkCmMKi0M4cA8ksO539Bes31sJAwqDQ="', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_turnOffEncryptionOnPrimaryChannel(capsys) -
-
-

Turn off encryption when there is a psk.

-
- -Expand source code - -
@pytest.mark.unit
-def test_turnOffEncryptionOnPrimaryChannel(capsys):
-    """Turn off encryption when there is a psk."""
-    anode = Node('foo', 'bar', noProto=True)
-
-    channel1 = Channel(index=1, role=1)
-    channel1.settings.modem_config = 3
-    # value from using "--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b "
-    channel1.settings.psk = b'\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++'
-
-    channel2 = Channel(index=2, role=0)
-    channel3 = Channel(index=3, role=0)
-    channel4 = Channel(index=4, role=0)
-    channel5 = Channel(index=5, role=0)
-    channel6 = Channel(index=6, role=0)
-    channel7 = Channel(index=7, role=0)
-    channel8 = Channel(index=8, role=0)
-
-    channels = [ channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8 ]
-
-    anode.channels = channels
-    anode.turnOffEncryptionOnPrimaryChannel()
-    out, err = capsys.readouterr()
-    assert re.search(r'Writing modified channels to device', out)
-    assert err == ''
-
-
-
-def test_writeConfig(caplog) -
-
-

Test writeConfig

-
- -Expand source code - -
@pytest.mark.unit
-def test_writeConfig(caplog):
-    """Test writeConfig"""
-    anode = Node('foo', 'bar', noProto=True)
-    radioConfig = RadioConfig()
-    anode.radioConfig = radioConfig
-
-    with caplog.at_level(logging.DEBUG):
-        anode.writeConfig()
-    assert re.search(r'Wrote config', caplog.text, re.MULTILINE)
-
-
-
-def test_writeConfig_with_no_radioConfig(capsys) -
-
-

Test writeConfig with no radioConfig.

-
- -Expand source code - -
@pytest.mark.unit
-def test_writeConfig_with_no_radioConfig(capsys):
-    """Test writeConfig with no radioConfig."""
-    anode = Node('foo', 'bar', noProto=True)
-
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        anode.writeConfig()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Error: No RadioConfig has been read', out)
-    assert err == ''
-
-
-
-
-
-

Classes

-
-
-class AdminMessage -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var CONFIRM_SET_CHANNEL_FIELD_NUMBER
-
-
-
-
var CONFIRM_SET_RADIO_FIELD_NUMBER
-
-
-
-
var DESCRIPTOR
-
-
-
-
var EXIT_SIMULATOR_FIELD_NUMBER
-
-
-
-
var GET_CHANNEL_REQUEST_FIELD_NUMBER
-
-
-
-
var GET_CHANNEL_RESPONSE_FIELD_NUMBER
-
-
-
-
var GET_OWNER_REQUEST_FIELD_NUMBER
-
-
-
-
var GET_OWNER_RESPONSE_FIELD_NUMBER
-
-
-
-
var GET_RADIO_REQUEST_FIELD_NUMBER
-
-
-
-
var GET_RADIO_RESPONSE_FIELD_NUMBER
-
-
-
-
var REBOOT_SECONDS_FIELD_NUMBER
-
-
-
-
var SET_CHANNEL_FIELD_NUMBER
-
-
-
-
var SET_OWNER_FIELD_NUMBER
-
-
-
-
var SET_RADIO_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var confirm_set_channel
-
-

Getter for confirm_set_channel.

-
- -Expand source code - -
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)
-
-
-
var confirm_set_radio
-
-

Getter for confirm_set_radio.

-
- -Expand source code - -
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)
-
-
-
var exit_simulator
-
-

Getter for exit_simulator.

-
- -Expand source code - -
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)
-
-
-
var get_channel_request
-
-

Getter for get_channel_request.

-
- -Expand source code - -
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)
-
-
-
var get_channel_response
-
-

Getter for get_channel_response.

-
- -Expand source code - -
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
-
-
-
var get_owner_request
-
-

Getter for get_owner_request.

-
- -Expand source code - -
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)
-
-
-
var get_owner_response
-
-

Getter for get_owner_response.

-
- -Expand source code - -
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
-
-
-
var get_radio_request
-
-

Getter for get_radio_request.

-
- -Expand source code - -
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)
-
-
-
var get_radio_response
-
-

Getter for get_radio_response.

-
- -Expand source code - -
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
-
-
-
var reboot_seconds
-
-

Getter for reboot_seconds.

-
- -Expand source code - -
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)
-
-
-
var set_channel
-
-

Getter for set_channel.

-
- -Expand source code - -
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
-
-
-
var set_owner
-
-

Getter for set_owner.

-
- -Expand source code - -
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
-
-
-
var set_radio
-
-

Getter for set_radio.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class Channel -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var DISABLED
-
-
-
-
var INDEX_FIELD_NUMBER
-
-
-
-
var PRIMARY
-
-
-
-
var ROLE_FIELD_NUMBER
-
-
-
-
var Role
-
-
-
-
var SECONDARY
-
-
-
-
var SETTINGS_FIELD_NUMBER
-
-
-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var index
-
-

Getter for index.

-
- -Expand source code - -
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)
-
-
-
var role
-
-

Getter for role.

-
- -Expand source code - -
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)
-
-
-
var settings
-
-

Getter for settings.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-class RadioConfig -(**kwargs) -
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-

Ancestors

-
    -
  • google.protobuf.message.Message
  • -
-

Class variables

-
-
var DESCRIPTOR
-
-
-
-
var PREFERENCES_FIELD_NUMBER
-
-
-
-
var UserPreferences
-
-

Abstract base class for protocol messages.

-

Protocol message classes are almost always generated by the protocol -compiler. -These generated types subclass Message and implement the methods -shown below.

-
-
-

Static methods

-
-
-def FromString(s) -
-
-
-
- -Expand source code - -
def FromString(s):
-  message = cls()
-  message.MergeFromString(s)
-  return message
-
-
-
-def RegisterExtension(extension_handle) -
-
-
-
- -Expand source code - -
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)
-
-
-
-

Instance variables

-
-
var preferences
-
-

Getter for preferences.

-
- -Expand source code - -
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
-
-
-
-

Methods

-
-
-def ByteSize(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def Clear(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def ClearField(self, field_name) -
-
-
-
- -Expand source code - -
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()
-
-
-
-def DiscardUnknownFields(self) -
-
-
-
- -Expand source code - -
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()
-
-
-
-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".

-
- -Expand source code - -
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
-
-
-
-def HasField(self, field_name) -
-
-
-
- -Expand source code - -
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
-
-
-
-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.

-
- -Expand source code - -
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
-
-
-
-def ListFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def MergeFrom(self, msg) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def MergeFromString(self, serialized) -
-
-
-
- -Expand source code - -
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.
-
-
-
-def SerializePartialToString(self, **kwargs) -
-
-
-
- -Expand source code - -
def SerializePartialToString(self, **kwargs):
-  out = BytesIO()
-  self._InternalSerialize(out.write, **kwargs)
-  return out.getvalue()
-
-
-
-def SerializeToString(self, **kwargs) -
-
-
-
- -Expand source code - -
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)
-
-
-
-def SetInParent(self) -
-
-

Sets the _cached_byte_size_dirty bit to true, -and propagates this to our listener iff this was a state change.

-
- -Expand source code - -
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()
-
-
-
-def UnknownFields(self) -
-
-
-
- -Expand source code - -
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
-
-
-
-def WhichOneof(self, oneof_name) -
-
-

Returns the name of the currently set field inside a oneof, or None.

-
- -Expand source code - -
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
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_remote_hardware.html b/docs/meshtastic/tests/test_remote_hardware.html deleted file mode 100644 index 9f5ca0f..0000000 --- a/docs/meshtastic/tests/test_remote_hardware.html +++ /dev/null @@ -1,304 +0,0 @@ - - - - - - -meshtastic.tests.test_remote_hardware API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_remote_hardware

-
-
-

Meshtastic unit tests for remote_hardware.py

-
- -Expand source code - -
"""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
-
-
-
-
-
-
-
-

Functions

-
-
-def test_RemoteHardwareClient() -
-
-

Test that we can instantiate a RemoteHardwareClient instance

-
- -Expand source code - -
@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()
-
-
-
-def test_RemoteHardwareClient_no_gpio_channel(capsys) -
-
-

Test that we can instantiate a RemoteHardwareClient instance but there is no channel named channel 'gpio'

-
- -Expand source code - -
@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 == ""
-
-
-
-def test_onGPIOreceive(capsys) -
-
-

Test onGPIOreceive

-
- -Expand source code - -
@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 == ''
-
-
-
-def test_readGPIOs(caplog) -
-
-

Test readGPIOs

-
- -Expand source code - -
@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()
-
-
-
-def test_sendHardware_no_nodeid() -
-
-

Test sending no nodeid to _sendHardware()

-
- -Expand source code - -
@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
-
-
-
-def test_watchGPIOs(caplog) -
-
-

Test watchGPIOs

-
- -Expand source code - -
@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()
-
-
-
-def test_writeGPIOs(caplog) -
-
-

Test writeGPIOs

-
- -Expand source code - -
@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()
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_serial_interface.html b/docs/meshtastic/tests/test_serial_interface.html deleted file mode 100644 index f3c8981..0000000 --- a/docs/meshtastic/tests/test_serial_interface.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - -meshtastic.tests.test_serial_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_serial_interface

-
-
-

Meshtastic unit tests for serial_interface.py

-
- -Expand source code - -
"""Meshtastic unit tests for serial_interface.py"""
-
-import re
-
-
-from unittest.mock import patch
-import pytest
-
-from ..serial_interface import SerialInterface
-
-@pytest.mark.unit
-@patch('serial.Serial')
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyUSBfake'])
-def test_SerialInterface_single_port(mocked_findPorts, mocked_serial):
-    """Test that we can instantiate a SerialInterface with a single port"""
-    iface = SerialInterface(noProto=True)
-    iface.showInfo()
-    iface.localNode.showInfo()
-    iface.close()
-    mocked_findPorts.assert_called()
-    mocked_serial.assert_called()
-
-
-@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=[])
-def test_SerialInterface_no_ports(mocked_findPorts, capsys):
-    """Test that we can instantiate a SerialInterface with no ports"""
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        SerialInterface(noProto=True)
-    mocked_findPorts.assert_called()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: No Meshtastic devices detected', out, re.MULTILINE)
-    assert err == ''
-
-
-@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyUSBfake1', '/dev/ttyUSBfake2'])
-def test_SerialInterface_multiple_ports(mocked_findPorts, capsys):
-    """Test that we can instantiate a SerialInterface with two ports"""
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        SerialInterface(noProto=True)
-    mocked_findPorts.assert_called()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: Multiple serial ports were detected', out, re.MULTILINE)
-    assert err == ''
-
-
-
-
-
-
-
-

Functions

-
-
-def test_SerialInterface_multiple_ports(mocked_findPorts, capsys) -
-
-

Test that we can instantiate a SerialInterface with two ports

-
- -Expand source code - -
@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyUSBfake1', '/dev/ttyUSBfake2'])
-def test_SerialInterface_multiple_ports(mocked_findPorts, capsys):
-    """Test that we can instantiate a SerialInterface with two ports"""
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        SerialInterface(noProto=True)
-    mocked_findPorts.assert_called()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: Multiple serial ports were detected', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_SerialInterface_no_ports(mocked_findPorts, capsys) -
-
-

Test that we can instantiate a SerialInterface with no ports

-
- -Expand source code - -
@pytest.mark.unit
-@patch('meshtastic.util.findPorts', return_value=[])
-def test_SerialInterface_no_ports(mocked_findPorts, capsys):
-    """Test that we can instantiate a SerialInterface with no ports"""
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        SerialInterface(noProto=True)
-    mocked_findPorts.assert_called()
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-    out, err = capsys.readouterr()
-    assert re.search(r'Warning: No Meshtastic devices detected', out, re.MULTILINE)
-    assert err == ''
-
-
-
-def test_SerialInterface_single_port(mocked_findPorts, mocked_serial) -
-
-

Test that we can instantiate a SerialInterface with a single port

-
- -Expand source code - -
@pytest.mark.unit
-@patch('serial.Serial')
-@patch('meshtastic.util.findPorts', return_value=['/dev/ttyUSBfake'])
-def test_SerialInterface_single_port(mocked_findPorts, mocked_serial):
-    """Test that we can instantiate a SerialInterface with a single port"""
-    iface = SerialInterface(noProto=True)
-    iface.showInfo()
-    iface.localNode.showInfo()
-    iface.close()
-    mocked_findPorts.assert_called()
-    mocked_serial.assert_called()
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_smoke1.html b/docs/meshtastic/tests/test_smoke1.html deleted file mode 100644 index e3a32c6..0000000 --- a/docs/meshtastic/tests/test_smoke1.html +++ /dev/null @@ -1,1822 +0,0 @@ - - - - - - -meshtastic.tests.test_smoke1 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_smoke1

-
-
-

Meshtastic smoke tests with a single device via USB

-
- -Expand source code - -
"""Meshtastic smoke tests with a single device via USB"""
-import re
-import subprocess
-import time
-import os
-
-# Do not like using hard coded sleeps, but it probably makes
-# sense to pause for the radio at apprpriate times
-import pytest
-
-from ..util import findPorts
-
-# seconds to pause after running a meshtastic command
-PAUSE_AFTER_COMMAND = 2
-PAUSE_AFTER_REBOOT = 7
-
-
-@pytest.mark.smoke1
-def test_smoke1_reboot():
-    """Test reboot"""
-    return_value, _ = subprocess.getstatusoutput('meshtastic --reboot')
-    assert return_value == 0
-    # pause for the radio to reset (10 seconds for the pause, and a few more seconds to be back up)
-    time.sleep(18)
-
-
-@pytest.mark.smoke1
-def test_smoke1_info():
-    """Test --info"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Owner', out, re.MULTILINE)
-    assert re.search(r'^My info', out, re.MULTILINE)
-    assert re.search(r'^Nodes in mesh', out, re.MULTILINE)
-    assert re.search(r'^Preferences', out, re.MULTILINE)
-    assert re.search(r'^Channels', out, re.MULTILINE)
-    assert re.search(r'^  PRIMARY', out, re.MULTILINE)
-    assert re.search(r'^Primary channel URL', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_sendping():
-    """Test --sendping"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --sendping')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Sending ping message', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_get_with_invalid_setting():
-    """Test '--get a_bad_setting'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --get a_bad_setting')
-    assert re.search(r'Choices in sorted order', out)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_set_with_invalid_setting():
-    """Test '--set a_bad_setting'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set a_bad_setting foo')
-    assert re.search(r'Choices in sorted order', out)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_ch_set_with_invalid_settingpatch_find_ports():
-    """Test '--ch-set with a_bad_setting'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set invalid_setting foo --ch-index 0')
-    assert re.search(r'Choices in sorted order', out)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_pos_fields():
-    """Test --pos-fields (with some values POS_ALTITUDE POS_ALT_MSL POS_BATTERY)"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --pos-fields POS_ALTITUDE POS_ALT_MSL POS_BATTERY')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Setting position fields to 35', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --pos-fields')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'POS_ALTITUDE', out, re.MULTILINE)
-    assert re.search(r'POS_ALT_MSL', out, re.MULTILINE)
-    assert re.search(r'POS_BATTERY', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_test_with_arg_but_no_hardware():
-    """Test --test
-       Note: Since only one device is connected, it will not do much.
-    """
-    return_value, out = subprocess.getstatusoutput('meshtastic --test')
-    assert re.search(r'^Warning: Must have at least two devices', out, re.MULTILINE)
-    assert return_value == 1
-
-
-@pytest.mark.smoke1
-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 file', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_seriallog_to_file():
-    """Test --seriallog to a file creates a file"""
-    filename = 'tmpoutput.txt'
-    if os.path.exists(f"{filename}"):
-        os.remove(f"{filename}")
-    return_value, _ = subprocess.getstatusoutput(f'meshtastic --info --seriallog {filename}')
-    assert os.path.exists(f"{filename}")
-    assert return_value == 0
-    os.remove(f"{filename}")
-
-
-@pytest.mark.smoke1
-def test_smoke1_qr():
-    """Test --qr"""
-    filename = 'tmpqr'
-    if os.path.exists(f"{filename}"):
-        os.remove(f"{filename}")
-    return_value, _ = subprocess.getstatusoutput(f'meshtastic --qr > {filename}')
-    assert os.path.exists(f"{filename}")
-    # not really testing that a valid qr code is created, just that the file size
-    # is reasonably big enough for a qr code
-    assert os.stat(f"{filename}").st_size > 20000
-    assert return_value == 0
-    os.remove(f"{filename}")
-
-
-@pytest.mark.smoke1
-def test_smoke1_nodes():
-    """Test --nodes"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --nodes')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^│   N │ User', out, re.MULTILINE)
-    assert re.search(r'^│   1 │', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_send_hello():
-    """Test --sendtext hello"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --sendtext hello')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Sending text message hello to \^all', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_port():
-    """Test --port"""
-    # first, get the ports
-    ports = findPorts()
-    # hopefully there is just one
-    assert len(ports) == 1
-    port = ports[0]
-    return_value, out = subprocess.getstatusoutput(f'meshtastic --port {port} --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Owner', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_set_is_router_true():
-    """Test --set is_router true"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set is_router true')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set is_router to true', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --get is_router')
-    assert re.search(r'^is_router: True', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_set_location_info():
-    """Test --setlat, --setlon and --setalt """
-    return_value, out = subprocess.getstatusoutput('meshtastic --setlat 32.7767 --setlon -96.7970 --setalt 1337')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Fixing altitude', out, re.MULTILINE)
-    assert re.search(r'^Fixing latitude', out, re.MULTILINE)
-    assert re.search(r'^Fixing longitude', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out2 = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'1337', out2, re.MULTILINE)
-    assert re.search(r'32.7767', out2, re.MULTILINE)
-    assert re.search(r'-96.797', out2, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_set_is_router_false():
-    """Test --set is_router false"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set is_router false')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set is_router to false', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --get is_router')
-    assert re.search(r'^is_router: False', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_set_owner():
-    """Test --set-owner name"""
-    # make sure the owner is not Joe
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-owner Bob')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Setting device owner to Bob', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search(r'Owner: Joe', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-owner Joe')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Setting device owner to Joe', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'Owner: Joe', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_set_team():
-    """Test --set-team """
-    # unset the team
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-team CLEAR')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Setting team to CLEAR', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-team CYAN')
-    assert re.search(r'Setting team to CYAN', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'CYAN', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_ch_values():
-    """Test --ch-longslow, --ch-longfast, --ch-mediumslow, --ch-mediumsfast,
-       --ch-shortslow, and --ch-shortfast arguments
-    """
-    exp = {
-            '--ch-longslow': 'Bw125Cr48Sf4096',
-            '--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'
-          }
-
-    for key, val in exp.items():
-        print(key, val)
-        return_value, out = subprocess.getstatusoutput(f'meshtastic {key}')
-        assert re.match(r'Connected to radio', out)
-        assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-        assert return_value == 0
-        # pause for the radio (might reboot)
-        time.sleep(PAUSE_AFTER_REBOOT)
-        return_value, out = subprocess.getstatusoutput('meshtastic --info')
-        assert re.search(val, out, re.MULTILINE)
-        assert return_value == 0
-        # pause for the radio
-        time.sleep(PAUSE_AFTER_COMMAND)
-
-
-@pytest.mark.smoke1
-def test_smoke1_ch_set_name():
-    """Test --ch-set name"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search(r'MyChannel', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set name MyChannel')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set name MyChannel --ch-index 0')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set name to MyChannel', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'MyChannel', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_ch_set_downlink_and_uplink():
-    """Test -ch-set downlink_enabled X and --ch-set uplink_enabled X"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set downlink_enabled false --ch-set uplink_enabled false')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set downlink_enabled false --ch-set uplink_enabled false --ch-index 0')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search(r'uplinkEnabled', out, re.MULTILINE)
-    assert not re.search(r'downlinkEnabled', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set downlink_enabled true --ch-set uplink_enabled true --ch-index 0')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set downlink_enabled to true', out, re.MULTILINE)
-    assert re.search(r'^Set uplink_enabled to true', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'uplinkEnabled', out, re.MULTILINE)
-    assert re.search(r'downlinkEnabled', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_ch_add_and_ch_del():
-    """Test --ch-add"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing')
-    assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-index 1 --ch-del')
-    assert re.search(r'Deleting channel 1', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-    # make sure the secondar channel is not there
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert not re.search(r'SECONDARY', out, re.MULTILINE)
-    assert not re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_ch_enable_and_disable():
-    """Test --ch-enable and --ch-disable"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing')
-    assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    # ensure they need to specify a --ch-index
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-disable')
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-disable --ch-index 1')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'DISABLED', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-enable --ch-index 1')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-@pytest.mark.smoke1
-def test_smoke1_ch_del_a_disabled_non_primary_channel():
-    """Test --ch-del will work on a disabled non-primary channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing')
-    assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    # ensure they need to specify a --ch-index
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-disable')
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert not re.search(r'DISABLED', out, re.MULTILINE)
-    assert not re.search(r'SECONDARY', out, re.MULTILINE)
-    assert not re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-@pytest.mark.smoke1
-def test_smoke1_attempt_to_delete_primary_channel():
-    """Test that we cannot delete the PRIMARY channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 0')
-    assert re.search(r'Warning: Cannot delete primary channel', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-@pytest.mark.smoke1
-def test_smoke1_attempt_to_disable_primary_channel():
-    """Test that we cannot disable the PRIMARY channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-disable --ch-index 0')
-    assert re.search(r'Warning: Cannot enable', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-@pytest.mark.smoke1
-def test_smoke1_attempt_to_enable_primary_channel():
-    """Test that we cannot enable the PRIMARY channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-enable --ch-index 0')
-    assert re.search(r'Warning: Cannot enable', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-@pytest.mark.smoke1
-def test_smoke1_ensure_ch_del_second_of_three_channels():
-    """Test that when we delete the 2nd of 3 channels, that it deletes the correct channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing1', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing2')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'testing2', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'testing2', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-@pytest.mark.smoke1
-def test_smoke1_ensure_ch_del_third_of_three_channels():
-    """Test that when we delete the 3rd of 3 channels, that it deletes the correct channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing1', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing2')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'testing2', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 2')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'testing1', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-@pytest.mark.smoke1
-def test_smoke1_ch_set_modem_config():
-    """Test --ch-set modem_config"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set modem_config Bw31_25Cr48Sf512')
-    assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search(r'Bw31_25Cr48Sf512', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set modem_config Bw31_25Cr48Sf512 --ch-index 0')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set modem_config to Bw31_25Cr48Sf512', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'Bw31_25Cr48Sf512', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_seturl_default():
-    """Test --seturl with default value"""
-    # set some channel value so we no longer have a default channel
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set name foo --ch-index 0')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    # ensure we no longer have a default primary channel
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search('CgUYAyIBAQ', out, re.MULTILINE)
-    assert return_value == 0
-    url = "https://www.meshtastic.org/d/#CgUYAyIBAQ"
-    return_value, out = subprocess.getstatusoutput(f"meshtastic --seturl {url}")
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search('CgUYAyIBAQ', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_seturl_invalid_url():
-    """Test --seturl with invalid url"""
-    # Note: This url is no longer a valid url.
-    url = "https://www.meshtastic.org/c/#GAMiENTxuzogKQdZ8Lz_q89Oab8qB0RlZmF1bHQ="
-    return_value, out = subprocess.getstatusoutput(f"meshtastic --seturl {url}")
-    assert re.match(r'Connected to radio', out)
-    assert re.search('Warning: There were no settings', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-@pytest.mark.smoke1
-def test_smoke1_configure():
-    """Test --configure"""
-    _ , out = subprocess.getstatusoutput(f"meshtastic --configure example_config.yaml")
-    assert re.match(r'Connected to radio', out)
-    assert re.search('^Setting device owner to Bob TBeam', out, re.MULTILINE)
-    assert re.search('^Fixing altitude at 304 meters', out, re.MULTILINE)
-    assert re.search('^Fixing latitude at 35.8', out, re.MULTILINE)
-    assert re.search('^Fixing longitude at -93.8', out, re.MULTILINE)
-    assert re.search('^Setting device position', out, re.MULTILINE)
-    assert re.search('^Set region to 1', out, re.MULTILINE)
-    assert re.search('^Set is_always_powered to true', out, re.MULTILINE)
-    assert re.search('^Set send_owner_interval to 2', out, re.MULTILINE)
-    assert re.search('^Set screen_on_secs to 31536000', out, re.MULTILINE)
-    assert re.search('^Set wait_bluetooth_secs to 31536000', out, re.MULTILINE)
-    assert re.search('^Writing modified preferences to device', out, re.MULTILINE)
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-
-
-@pytest.mark.smoke1
-def test_smoke1_set_ham():
-    """Test --set-ham
-       Note: Do a factory reset after this setting so it is very short-lived.
-    """
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-ham KI1234')
-    assert re.search(r'Setting Ham ID', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'Owner: KI1234', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_set_wifi_settings():
-    """Test --set wifi_ssid and --set wifi_password"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set wifi_ssid "some_ssid" --set wifi_password "temp1234"')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set wifi_ssid to some_ssid', out, re.MULTILINE)
-    assert re.search(r'^Set wifi_password to temp1234', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --get wifi_ssid --get wifi_password')
-    assert re.search(r'^wifi_ssid: some_ssid', out, re.MULTILINE)
-    assert re.search(r'^wifi_password: sekrit', out, re.MULTILINE)
-    assert return_value == 0
-
-
-@pytest.mark.smoke1
-def test_smoke1_factory_reset():
-    """Test factory reset"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set factory_reset true')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set factory_reset to true', out, re.MULTILINE)
-    assert re.search(r'^Writing modified preferences to device', out, re.MULTILINE)
-    assert return_value == 0
-    # NOTE: The radio may not be responsive after this, may need to do a manual reboot
-    # by pressing the button
-
-
-
-
-
-
-
-

Functions

-
-
-def test_ch_set_with_invalid_settingpatch_find_ports() -
-
-

Test '–ch-set with a_bad_setting'.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_ch_set_with_invalid_settingpatch_find_ports():
-    """Test '--ch-set with a_bad_setting'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set invalid_setting foo --ch-index 0')
-    assert re.search(r'Choices in sorted order', out)
-    assert return_value == 0
-
-
-
-def test_get_with_invalid_setting() -
-
-

Test '–get a_bad_setting'.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_get_with_invalid_setting():
-    """Test '--get a_bad_setting'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --get a_bad_setting')
-    assert re.search(r'Choices in sorted order', out)
-    assert return_value == 0
-
-
-
-def test_set_with_invalid_setting() -
-
-

Test '–set a_bad_setting'.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_set_with_invalid_setting():
-    """Test '--set a_bad_setting'."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set a_bad_setting foo')
-    assert re.search(r'Choices in sorted order', out)
-    assert return_value == 0
-
-
-
-def test_smoke1_attempt_to_delete_primary_channel() -
-
-

Test that we cannot delete the PRIMARY channel.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_attempt_to_delete_primary_channel():
-    """Test that we cannot delete the PRIMARY channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 0')
-    assert re.search(r'Warning: Cannot delete primary channel', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-
-def test_smoke1_attempt_to_disable_primary_channel() -
-
-

Test that we cannot disable the PRIMARY channel.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_attempt_to_disable_primary_channel():
-    """Test that we cannot disable the PRIMARY channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-disable --ch-index 0')
-    assert re.search(r'Warning: Cannot enable', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-
-def test_smoke1_attempt_to_enable_primary_channel() -
-
-

Test that we cannot enable the PRIMARY channel.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_attempt_to_enable_primary_channel():
-    """Test that we cannot enable the PRIMARY channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-enable --ch-index 0')
-    assert re.search(r'Warning: Cannot enable', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-
-def test_smoke1_ch_add_and_ch_del() -
-
-

Test –ch-add

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_ch_add_and_ch_del():
-    """Test --ch-add"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing')
-    assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-index 1 --ch-del')
-    assert re.search(r'Deleting channel 1', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-    # make sure the secondar channel is not there
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert not re.search(r'SECONDARY', out, re.MULTILINE)
-    assert not re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_ch_del_a_disabled_non_primary_channel() -
-
-

Test –ch-del will work on a disabled non-primary channel.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_ch_del_a_disabled_non_primary_channel():
-    """Test --ch-del will work on a disabled non-primary channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing')
-    assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    # ensure they need to specify a --ch-index
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-disable')
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert not re.search(r'DISABLED', out, re.MULTILINE)
-    assert not re.search(r'SECONDARY', out, re.MULTILINE)
-    assert not re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-
-def test_smoke1_ch_enable_and_disable() -
-
-

Test –ch-enable and –ch-disable

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_ch_enable_and_disable():
-    """Test --ch-enable and --ch-disable"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing')
-    assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    # ensure they need to specify a --ch-index
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-disable')
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-disable --ch-index 1')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'DISABLED', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-enable --ch-index 1')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
- -
-

Test -ch-set downlink_enabled X and –ch-set uplink_enabled X

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_ch_set_downlink_and_uplink():
-    """Test -ch-set downlink_enabled X and --ch-set uplink_enabled X"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set downlink_enabled false --ch-set uplink_enabled false')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set downlink_enabled false --ch-set uplink_enabled false --ch-index 0')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search(r'uplinkEnabled', out, re.MULTILINE)
-    assert not re.search(r'downlinkEnabled', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set downlink_enabled true --ch-set uplink_enabled true --ch-index 0')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set downlink_enabled to true', out, re.MULTILINE)
-    assert re.search(r'^Set uplink_enabled to true', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'uplinkEnabled', out, re.MULTILINE)
-    assert re.search(r'downlinkEnabled', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_ch_set_modem_config() -
-
-

Test –ch-set modem_config

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_ch_set_modem_config():
-    """Test --ch-set modem_config"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set modem_config Bw31_25Cr48Sf512')
-    assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search(r'Bw31_25Cr48Sf512', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set modem_config Bw31_25Cr48Sf512 --ch-index 0')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set modem_config to Bw31_25Cr48Sf512', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'Bw31_25Cr48Sf512', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_ch_set_name() -
-
-

Test –ch-set name

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_ch_set_name():
-    """Test --ch-set name"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search(r'MyChannel', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set name MyChannel')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'Warning: Need to specify', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set name MyChannel --ch-index 0')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set name to MyChannel', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'MyChannel', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_ch_values() -
-
-

Test –ch-longslow, –ch-longfast, –ch-mediumslow, –ch-mediumsfast, -–ch-shortslow, and –ch-shortfast arguments

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_ch_values():
-    """Test --ch-longslow, --ch-longfast, --ch-mediumslow, --ch-mediumsfast,
-       --ch-shortslow, and --ch-shortfast arguments
-    """
-    exp = {
-            '--ch-longslow': 'Bw125Cr48Sf4096',
-            '--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'
-          }
-
-    for key, val in exp.items():
-        print(key, val)
-        return_value, out = subprocess.getstatusoutput(f'meshtastic {key}')
-        assert re.match(r'Connected to radio', out)
-        assert re.search(r'Writing modified channels to device', out, re.MULTILINE)
-        assert return_value == 0
-        # pause for the radio (might reboot)
-        time.sleep(PAUSE_AFTER_REBOOT)
-        return_value, out = subprocess.getstatusoutput('meshtastic --info')
-        assert re.search(val, out, re.MULTILINE)
-        assert return_value == 0
-        # pause for the radio
-        time.sleep(PAUSE_AFTER_COMMAND)
-
-
-
-def test_smoke1_configure() -
-
-

Test –configure

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_configure():
-    """Test --configure"""
-    _ , out = subprocess.getstatusoutput(f"meshtastic --configure example_config.yaml")
-    assert re.match(r'Connected to radio', out)
-    assert re.search('^Setting device owner to Bob TBeam', out, re.MULTILINE)
-    assert re.search('^Fixing altitude at 304 meters', out, re.MULTILINE)
-    assert re.search('^Fixing latitude at 35.8', out, re.MULTILINE)
-    assert re.search('^Fixing longitude at -93.8', out, re.MULTILINE)
-    assert re.search('^Setting device position', out, re.MULTILINE)
-    assert re.search('^Set region to 1', out, re.MULTILINE)
-    assert re.search('^Set is_always_powered to true', out, re.MULTILINE)
-    assert re.search('^Set send_owner_interval to 2', out, re.MULTILINE)
-    assert re.search('^Set screen_on_secs to 31536000', out, re.MULTILINE)
-    assert re.search('^Set wait_bluetooth_secs to 31536000', out, re.MULTILINE)
-    assert re.search('^Writing modified preferences to device', out, re.MULTILINE)
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-
-
-
-def test_smoke1_debug() -
-
-

Test –debug

-
- -Expand source code - -
@pytest.mark.smoke1
-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 file', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_ensure_ch_del_second_of_three_channels() -
-
-

Test that when we delete the 2nd of 3 channels, that it deletes the correct channel.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_ensure_ch_del_second_of_three_channels():
-    """Test that when we delete the 2nd of 3 channels, that it deletes the correct channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing1', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing2')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'testing2', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'testing2', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-
-def test_smoke1_ensure_ch_del_third_of_three_channels() -
-
-

Test that when we delete the 3rd of 3 channels, that it deletes the correct channel.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_ensure_ch_del_third_of_three_channels():
-    """Test that when we delete the 3rd of 3 channels, that it deletes the correct channel."""
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'SECONDARY', out, re.MULTILINE)
-    assert re.search(r'testing1', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-add testing2')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'testing2', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 2')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'testing1', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-del --ch-index 1')
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-
-def test_smoke1_factory_reset() -
-
-

Test factory reset

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_factory_reset():
-    """Test factory reset"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set factory_reset true')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set factory_reset to true', out, re.MULTILINE)
-    assert re.search(r'^Writing modified preferences to device', out, re.MULTILINE)
-    assert return_value == 0
-    # NOTE: The radio may not be responsive after this, may need to do a manual reboot
-    # by pressing the button
-
-
-
-def test_smoke1_info() -
-
-

Test –info

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_info():
-    """Test --info"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Owner', out, re.MULTILINE)
-    assert re.search(r'^My info', out, re.MULTILINE)
-    assert re.search(r'^Nodes in mesh', out, re.MULTILINE)
-    assert re.search(r'^Preferences', out, re.MULTILINE)
-    assert re.search(r'^Channels', out, re.MULTILINE)
-    assert re.search(r'^  PRIMARY', out, re.MULTILINE)
-    assert re.search(r'^Primary channel URL', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_nodes() -
-
-

Test –nodes

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_nodes():
-    """Test --nodes"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --nodes')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^│   N │ User', out, re.MULTILINE)
-    assert re.search(r'^│   1 │', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_port() -
-
-

Test –port

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_port():
-    """Test --port"""
-    # first, get the ports
-    ports = findPorts()
-    # hopefully there is just one
-    assert len(ports) == 1
-    port = ports[0]
-    return_value, out = subprocess.getstatusoutput(f'meshtastic --port {port} --info')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Owner', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_pos_fields() -
-
-

Test –pos-fields (with some values POS_ALTITUDE POS_ALT_MSL POS_BATTERY)

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_pos_fields():
-    """Test --pos-fields (with some values POS_ALTITUDE POS_ALT_MSL POS_BATTERY)"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --pos-fields POS_ALTITUDE POS_ALT_MSL POS_BATTERY')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Setting position fields to 35', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --pos-fields')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'POS_ALTITUDE', out, re.MULTILINE)
-    assert re.search(r'POS_ALT_MSL', out, re.MULTILINE)
-    assert re.search(r'POS_BATTERY', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_qr() -
-
-

Test –qr

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_qr():
-    """Test --qr"""
-    filename = 'tmpqr'
-    if os.path.exists(f"{filename}"):
-        os.remove(f"{filename}")
-    return_value, _ = subprocess.getstatusoutput(f'meshtastic --qr > {filename}')
-    assert os.path.exists(f"{filename}")
-    # not really testing that a valid qr code is created, just that the file size
-    # is reasonably big enough for a qr code
-    assert os.stat(f"{filename}").st_size > 20000
-    assert return_value == 0
-    os.remove(f"{filename}")
-
-
-
-def test_smoke1_reboot() -
-
-

Test reboot

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_reboot():
-    """Test reboot"""
-    return_value, _ = subprocess.getstatusoutput('meshtastic --reboot')
-    assert return_value == 0
-    # pause for the radio to reset (10 seconds for the pause, and a few more seconds to be back up)
-    time.sleep(18)
-
-
-
-def test_smoke1_send_hello() -
-
-

Test –sendtext hello

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_send_hello():
-    """Test --sendtext hello"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --sendtext hello')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Sending text message hello to \^all', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_sendping() -
-
-

Test –sendping

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_sendping():
-    """Test --sendping"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --sendping')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Sending ping message', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_seriallog_to_file() -
-
-

Test –seriallog to a file creates a file

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_seriallog_to_file():
-    """Test --seriallog to a file creates a file"""
-    filename = 'tmpoutput.txt'
-    if os.path.exists(f"{filename}"):
-        os.remove(f"{filename}")
-    return_value, _ = subprocess.getstatusoutput(f'meshtastic --info --seriallog {filename}')
-    assert os.path.exists(f"{filename}")
-    assert return_value == 0
-    os.remove(f"{filename}")
-
-
-
-def test_smoke1_set_ham() -
-
-

Test –set-ham -Note: Do a factory reset after this setting so it is very short-lived.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_set_ham():
-    """Test --set-ham
-       Note: Do a factory reset after this setting so it is very short-lived.
-    """
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-ham KI1234')
-    assert re.search(r'Setting Ham ID', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'Owner: KI1234', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_set_is_router_false() -
-
-

Test –set is_router false

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_set_is_router_false():
-    """Test --set is_router false"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set is_router false')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set is_router to false', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --get is_router')
-    assert re.search(r'^is_router: False', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_set_is_router_true() -
-
-

Test –set is_router true

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_set_is_router_true():
-    """Test --set is_router true"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set is_router true')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set is_router to true', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --get is_router')
-    assert re.search(r'^is_router: True', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_set_location_info() -
-
-

Test –setlat, –setlon and –setalt

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_set_location_info():
-    """Test --setlat, --setlon and --setalt """
-    return_value, out = subprocess.getstatusoutput('meshtastic --setlat 32.7767 --setlon -96.7970 --setalt 1337')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Fixing altitude', out, re.MULTILINE)
-    assert re.search(r'^Fixing latitude', out, re.MULTILINE)
-    assert re.search(r'^Fixing longitude', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out2 = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'1337', out2, re.MULTILINE)
-    assert re.search(r'32.7767', out2, re.MULTILINE)
-    assert re.search(r'-96.797', out2, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_set_owner() -
-
-

Test –set-owner name

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_set_owner():
-    """Test --set-owner name"""
-    # make sure the owner is not Joe
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-owner Bob')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Setting device owner to Bob', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search(r'Owner: Joe', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-owner Joe')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Setting device owner to Joe', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'Owner: Joe', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_set_team() -
-
-

Test –set-team

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_set_team():
-    """Test --set-team """
-    # unset the team
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-team CLEAR')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Setting team to CLEAR', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-    return_value, out = subprocess.getstatusoutput('meshtastic --set-team CYAN')
-    assert re.search(r'Setting team to CYAN', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_REBOOT)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'CYAN', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_set_wifi_settings() -
-
-

Test –set wifi_ssid and –set wifi_password

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_set_wifi_settings():
-    """Test --set wifi_ssid and --set wifi_password"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --set wifi_ssid "some_ssid" --set wifi_password "temp1234"')
-    assert re.match(r'Connected to radio', out)
-    assert re.search(r'^Set wifi_ssid to some_ssid', out, re.MULTILINE)
-    assert re.search(r'^Set wifi_password to temp1234', out, re.MULTILINE)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --get wifi_ssid --get wifi_password')
-    assert re.search(r'^wifi_ssid: some_ssid', out, re.MULTILINE)
-    assert re.search(r'^wifi_password: sekrit', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_seturl_default() -
-
-

Test –seturl with default value

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_seturl_default():
-    """Test --seturl with default value"""
-    # set some channel value so we no longer have a default channel
-    return_value, out = subprocess.getstatusoutput('meshtastic --ch-set name foo --ch-index 0')
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    # ensure we no longer have a default primary channel
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert not re.search('CgUYAyIBAQ', out, re.MULTILINE)
-    assert return_value == 0
-    url = "https://www.meshtastic.org/d/#CgUYAyIBAQ"
-    return_value, out = subprocess.getstatusoutput(f"meshtastic --seturl {url}")
-    assert re.match(r'Connected to radio', out)
-    assert return_value == 0
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search('CgUYAyIBAQ', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-def test_smoke1_seturl_invalid_url() -
-
-

Test –seturl with invalid url

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_seturl_invalid_url():
-    """Test --seturl with invalid url"""
-    # Note: This url is no longer a valid url.
-    url = "https://www.meshtastic.org/c/#GAMiENTxuzogKQdZ8Lz_q89Oab8qB0RlZmF1bHQ="
-    return_value, out = subprocess.getstatusoutput(f"meshtastic --seturl {url}")
-    assert re.match(r'Connected to radio', out)
-    assert re.search('Warning: There were no settings', out, re.MULTILINE)
-    assert return_value == 1
-    # pause for the radio
-    time.sleep(PAUSE_AFTER_COMMAND)
-
-
-
-def test_smoke1_test_with_arg_but_no_hardware() -
-
-

Test –test -Note: Since only one device is connected, it will not do much.

-
- -Expand source code - -
@pytest.mark.smoke1
-def test_smoke1_test_with_arg_but_no_hardware():
-    """Test --test
-       Note: Since only one device is connected, it will not do much.
-    """
-    return_value, out = subprocess.getstatusoutput('meshtastic --test')
-    assert re.search(r'^Warning: Must have at least two devices', out, re.MULTILINE)
-    assert return_value == 1
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_smoke2.html b/docs/meshtastic/tests/test_smoke2.html deleted file mode 100644 index 2cfb2e7..0000000 --- a/docs/meshtastic/tests/test_smoke2.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - -meshtastic.tests.test_smoke2 API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_smoke2

-
-
-

Meshtastic smoke tests with 2 devices connected via USB

-
- -Expand source code - -
"""Meshtastic smoke tests with 2 devices connected via USB"""
-import re
-import subprocess
-
-import pytest
-
-
-@pytest.mark.smoke2
-def test_smoke2_info():
-    """Test --info with 2 devices connected serially"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'Warning: Multiple', out, re.MULTILINE)
-    assert return_value == 1
-
-
-@pytest.mark.smoke2
-def test_smoke2_test():
-    """Test --test"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --test')
-    assert re.search(r'Writing serial debugging', out, re.MULTILINE)
-    assert re.search(r'Ports opened', out, re.MULTILINE)
-    assert re.search(r'Running 5 tests', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-
-
-
-
-

Functions

-
-
-def test_smoke2_info() -
-
-

Test –info with 2 devices connected serially

-
- -Expand source code - -
@pytest.mark.smoke2
-def test_smoke2_info():
-    """Test --info with 2 devices connected serially"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --info')
-    assert re.search(r'Warning: Multiple', out, re.MULTILINE)
-    assert return_value == 1
-
-
-
-def test_smoke2_test() -
-
-

Test –test

-
- -Expand source code - -
@pytest.mark.smoke2
-def test_smoke2_test():
-    """Test --test"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --test')
-    assert re.search(r'Writing serial debugging', out, re.MULTILINE)
-    assert re.search(r'Ports opened', out, re.MULTILINE)
-    assert re.search(r'Running 5 tests', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_smoke_wifi.html b/docs/meshtastic/tests/test_smoke_wifi.html deleted file mode 100644 index 3e2e28e..0000000 --- a/docs/meshtastic/tests/test_smoke_wifi.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - -meshtastic.tests.test_smoke_wifi API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_smoke_wifi

-
-
-

Meshtastic smoke tests a device setup with wifi.

-

Need to have run the following on an esp32 device: -meshtastic –set wifi_ssid 'foo' –set wifi_password 'sekret'

-
- -Expand source code - -
"""Meshtastic smoke tests a device setup with wifi.
-
-   Need to have run the following on an esp32 device:
-      meshtastic --set wifi_ssid 'foo' --set wifi_password 'sekret'
-"""
-import re
-import subprocess
-
-import pytest
-
-
-@pytest.mark.smokewifi
-def test_smokewifi_info():
-    """Test --info"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --info --host meshtastic.local')
-    assert re.search(r'^Owner', out, re.MULTILINE)
-    assert re.search(r'^My info', out, re.MULTILINE)
-    assert re.search(r'^Nodes in mesh', out, re.MULTILINE)
-    assert re.search(r'^Preferences', out, re.MULTILINE)
-    assert re.search(r'^Channels', out, re.MULTILINE)
-    assert re.search(r'^  PRIMARY', out, re.MULTILINE)
-    assert re.search(r'^Primary channel URL', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-
-
-
-
-

Functions

-
-
-def test_smokewifi_info() -
-
-

Test –info

-
- -Expand source code - -
@pytest.mark.smokewifi
-def test_smokewifi_info():
-    """Test --info"""
-    return_value, out = subprocess.getstatusoutput('meshtastic --info --host meshtastic.local')
-    assert re.search(r'^Owner', out, re.MULTILINE)
-    assert re.search(r'^My info', out, re.MULTILINE)
-    assert re.search(r'^Nodes in mesh', out, re.MULTILINE)
-    assert re.search(r'^Preferences', out, re.MULTILINE)
-    assert re.search(r'^Channels', out, re.MULTILINE)
-    assert re.search(r'^  PRIMARY', out, re.MULTILINE)
-    assert re.search(r'^Primary channel URL', out, re.MULTILINE)
-    assert return_value == 0
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_stream_interface.html b/docs/meshtastic/tests/test_stream_interface.html deleted file mode 100644 index 6702fd9..0000000 --- a/docs/meshtastic/tests/test_stream_interface.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - -meshtastic.tests.test_stream_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_stream_interface

-
-
-

Meshtastic unit tests for stream_interface.py

-
- -Expand source code - -
"""Meshtastic unit tests for stream_interface.py"""
-
-import logging
-import re
-
-from unittest.mock import MagicMock
-import pytest
-
-from ..stream_interface import StreamInterface
-
-
-@pytest.mark.unit
-def test_StreamInterface():
-    """Test that we cannot instantiate a StreamInterface based on noProto"""
-    with pytest.raises(Exception) as pytest_wrapped_e:
-        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)
-
-
-
-
-
-
-
-

Functions

-
-
-def test_StreamInterface() -
-
-

Test that we cannot instantiate a StreamInterface based on noProto

-
- -Expand source code - -
@pytest.mark.unit
-def test_StreamInterface():
-    """Test that we cannot instantiate a StreamInterface based on noProto"""
-    with pytest.raises(Exception) as pytest_wrapped_e:
-        StreamInterface()
-    assert pytest_wrapped_e.type == Exception
-
-
-
-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

-
- -Expand source code - -
@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
-
-
-
-def test_sendToRadioImpl(caplog, reset_globals) -
-
-

Test _sendToRadioImpl()

-
- -Expand source code - -
@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)
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_tcp_interface.html b/docs/meshtastic/tests/test_tcp_interface.html deleted file mode 100644 index 0753c11..0000000 --- a/docs/meshtastic/tests/test_tcp_interface.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - -meshtastic.tests.test_tcp_interface API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_tcp_interface

-
-
-

Meshtastic unit tests for tcp_interface.py

-
- -Expand source code - -
"""Meshtastic unit tests for tcp_interface.py"""
-
-import re
-
-from unittest.mock import patch
-import pytest
-
-from ..tcp_interface import TCPInterface
-
-
-@pytest.mark.unit
-def test_TCPInterface(capsys):
-    """Test that we can instantiate a TCPInterface"""
-    with patch('socket.socket') as mock_socket:
-        iface = TCPInterface(hostname='localhost', noProto=True)
-        iface.showInfo()
-        iface.localNode.showInfo()
-        out, err = capsys.readouterr()
-        assert re.search(r'Owner: None \(None\)', out, re.MULTILINE)
-        assert re.search(r'Nodes', out, re.MULTILINE)
-        assert re.search(r'Preferences', out, re.MULTILINE)
-        assert re.search(r'Channels', out, re.MULTILINE)
-        assert re.search(r'Primary channel URL', out, re.MULTILINE)
-        assert err == ''
-        assert mock_socket.called
-        iface.close()
-
-
-
-
-
-
-
-

Functions

-
-
-def test_TCPInterface(capsys) -
-
-

Test that we can instantiate a TCPInterface

-
- -Expand source code - -
@pytest.mark.unit
-def test_TCPInterface(capsys):
-    """Test that we can instantiate a TCPInterface"""
-    with patch('socket.socket') as mock_socket:
-        iface = TCPInterface(hostname='localhost', noProto=True)
-        iface.showInfo()
-        iface.localNode.showInfo()
-        out, err = capsys.readouterr()
-        assert re.search(r'Owner: None \(None\)', out, re.MULTILINE)
-        assert re.search(r'Nodes', out, re.MULTILINE)
-        assert re.search(r'Preferences', out, re.MULTILINE)
-        assert re.search(r'Channels', out, re.MULTILINE)
-        assert re.search(r'Primary channel URL', out, re.MULTILINE)
-        assert err == ''
-        assert mock_socket.called
-        iface.close()
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tests/test_util.html b/docs/meshtastic/tests/test_util.html deleted file mode 100644 index 5892866..0000000 --- a/docs/meshtastic/tests/test_util.html +++ /dev/null @@ -1,519 +0,0 @@ - - - - - - -meshtastic.tests.test_util API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tests.test_util

-
-
-

Meshtastic unit tests for util.py

-
- -Expand source code - -
"""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,
-                             quoteBooleans, catchAndIgnore)
-
-
-@pytest.mark.unit
-def test_genPSK256():
-    """Test genPSK256"""
-    assert genPSK256() != ''
-
-
-@pytest.mark.unit
-def test_fromStr():
-    """Test fromStr"""
-    assert fromStr('') == b''
-    assert fromStr('0x12') == b'\x12'
-    assert fromStr('t')
-    assert fromStr('T')
-    assert fromStr('true')
-    assert fromStr('True')
-    assert fromStr('yes')
-    assert fromStr('Yes')
-    assert fromStr('f') is False
-    assert fromStr('F') is False
-    assert fromStr('false') is False
-    assert fromStr('False') is False
-    assert fromStr('no') is False
-    assert fromStr('No') is False
-    assert fromStr('100.01') == 100.01
-    assert fromStr('123') == 123
-    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"""
-    assert fromPSK('random') != ''
-    assert fromPSK('none') == b'\x00'
-    assert fromPSK('default') == b'\x01'
-    assert fromPSK('simple22') == b'\x17'
-    assert fromPSK('trash') == 'trash'
-
-
-@pytest.mark.unit
-def test_stripnl():
-    """Test stripnl"""
-    assert stripnl('') == ''
-    assert stripnl('a\n') == 'a'
-    assert stripnl(' a \n ') == 'a'
-    assert stripnl('a\nb') == 'a b'
-
-
-@pytest.mark.unit
-def test_pskToString_empty_string():
-    """Test pskToString empty string"""
-    assert pskToString('') == 'unencrypted'
-
-
-@pytest.mark.unit
-def test_pskToString_string():
-    """Test pskToString string"""
-    assert pskToString('hunter123') == 'secret'
-
-
-@pytest.mark.unit
-def test_pskToString_one_byte_zero_value():
-    """Test pskToString one byte that is value of 0"""
-    assert pskToString(bytes([0x00])) == 'unencrypted'
-
-
-@pytest.mark.unit
-def test_pskToString_one_byte_non_zero_value():
-    """Test pskToString one byte that is non-zero"""
-    assert pskToString(bytes([0x01])) == 'default'
-
-
-@pytest.mark.unit
-def test_pskToString_many_bytes():
-    """Test pskToString many bytes"""
-    assert pskToString(bytes([0x02, 0x01])) == 'secret'
-
-
-@pytest.mark.unit
-def test_pskToString_simple():
-    """Test pskToString simple"""
-    assert pskToString(bytes([0x03])) == 'simple2'
-
-
-@pytest.mark.unit
-def test_our_exit_zero_return_value():
-    """Test our_exit with a zero return value"""
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        our_exit("Warning: Some message", 0)
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-
-
-@pytest.mark.unit
-def test_our_exit_non_zero_return_value():
-    """Test our_exit with a non-zero return value"""
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        our_exit("Error: Some message", 1)
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-@pytest.mark.unit
-def test_fixme():
-    """Test fixme()"""
-    with pytest.raises(Exception) as pytest_wrapped_e:
-        fixme("some exception")
-    assert pytest_wrapped_e.type == Exception
-
-
-@pytest.mark.unit
-def test_support_info(capsys):
-    """Test support_info"""
-    support_info()
-    out, err = capsys.readouterr()
-    assert re.search(r'System', out, re.MULTILINE)
-    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 == ''
-
-
-@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)
-
-
-
-
-
-
-
-

Functions

-
-
-def test_catchAndIgnore(caplog) -
-
-

Test catchAndIgnore() does not actually throw an exception, but just logs

-
- -Expand source code - -
@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)
-
-
-
-def test_fixme() -
-
-

Test fixme()

-
- -Expand source code - -
@pytest.mark.unit
-def test_fixme():
-    """Test fixme()"""
-    with pytest.raises(Exception) as pytest_wrapped_e:
-        fixme("some exception")
-    assert pytest_wrapped_e.type == Exception
-
-
-
-def test_fromPSK() -
-
-

Test fromPSK

-
- -Expand source code - -
@pytest.mark.unit
-def test_fromPSK():
-    """Test fromPSK"""
-    assert fromPSK('random') != ''
-    assert fromPSK('none') == b'\x00'
-    assert fromPSK('default') == b'\x01'
-    assert fromPSK('simple22') == b'\x17'
-    assert fromPSK('trash') == 'trash'
-
-
-
-def test_fromStr() -
-
-

Test fromStr

-
- -Expand source code - -
@pytest.mark.unit
-def test_fromStr():
-    """Test fromStr"""
-    assert fromStr('') == b''
-    assert fromStr('0x12') == b'\x12'
-    assert fromStr('t')
-    assert fromStr('T')
-    assert fromStr('true')
-    assert fromStr('True')
-    assert fromStr('yes')
-    assert fromStr('Yes')
-    assert fromStr('f') is False
-    assert fromStr('F') is False
-    assert fromStr('false') is False
-    assert fromStr('False') is False
-    assert fromStr('no') is False
-    assert fromStr('No') is False
-    assert fromStr('100.01') == 100.01
-    assert fromStr('123') == 123
-    assert fromStr('abc') == 'abc'
-
-
-
-def test_genPSK256() -
-
-

Test genPSK256

-
- -Expand source code - -
@pytest.mark.unit
-def test_genPSK256():
-    """Test genPSK256"""
-    assert genPSK256() != ''
-
-
-
-def test_our_exit_non_zero_return_value() -
-
-

Test our_exit with a non-zero return value

-
- -Expand source code - -
@pytest.mark.unit
-def test_our_exit_non_zero_return_value():
-    """Test our_exit with a non-zero return value"""
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        our_exit("Error: Some message", 1)
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 1
-
-
-
-def test_our_exit_zero_return_value() -
-
-

Test our_exit with a zero return value

-
- -Expand source code - -
@pytest.mark.unit
-def test_our_exit_zero_return_value():
-    """Test our_exit with a zero return value"""
-    with pytest.raises(SystemExit) as pytest_wrapped_e:
-        our_exit("Warning: Some message", 0)
-    assert pytest_wrapped_e.type == SystemExit
-    assert pytest_wrapped_e.value.code == 0
-
-
-
-def test_pskToString_empty_string() -
-
-

Test pskToString empty string

-
- -Expand source code - -
@pytest.mark.unit
-def test_pskToString_empty_string():
-    """Test pskToString empty string"""
-    assert pskToString('') == 'unencrypted'
-
-
-
-def test_pskToString_many_bytes() -
-
-

Test pskToString many bytes

-
- -Expand source code - -
@pytest.mark.unit
-def test_pskToString_many_bytes():
-    """Test pskToString many bytes"""
-    assert pskToString(bytes([0x02, 0x01])) == 'secret'
-
-
-
-def test_pskToString_one_byte_non_zero_value() -
-
-

Test pskToString one byte that is non-zero

-
- -Expand source code - -
@pytest.mark.unit
-def test_pskToString_one_byte_non_zero_value():
-    """Test pskToString one byte that is non-zero"""
-    assert pskToString(bytes([0x01])) == 'default'
-
-
-
-def test_pskToString_one_byte_zero_value() -
-
-

Test pskToString one byte that is value of 0

-
- -Expand source code - -
@pytest.mark.unit
-def test_pskToString_one_byte_zero_value():
-    """Test pskToString one byte that is value of 0"""
-    assert pskToString(bytes([0x00])) == 'unencrypted'
-
-
-
-def test_pskToString_simple() -
-
-

Test pskToString simple

-
- -Expand source code - -
@pytest.mark.unit
-def test_pskToString_simple():
-    """Test pskToString simple"""
-    assert pskToString(bytes([0x03])) == 'simple2'
-
-
-
-def test_pskToString_string() -
-
-

Test pskToString string

-
- -Expand source code - -
@pytest.mark.unit
-def test_pskToString_string():
-    """Test pskToString string"""
-    assert pskToString('hunter123') == 'secret'
-
-
-
-def test_quoteBooleans() -
-
-

Test quoteBooleans

-
- -Expand source code - -
@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'"
-
-
-
-def test_stripnl() -
-
-

Test stripnl

-
- -Expand source code - -
@pytest.mark.unit
-def test_stripnl():
-    """Test stripnl"""
-    assert stripnl('') == ''
-    assert stripnl('a\n') == 'a'
-    assert stripnl(' a \n ') == 'a'
-    assert stripnl('a\nb') == 'a b'
-
-
-
-def test_support_info(capsys) -
-
-

Test support_info

-
- -Expand source code - -
@pytest.mark.unit
-def test_support_info(capsys):
-    """Test support_info"""
-    support_info()
-    out, err = capsys.readouterr()
-    assert re.search(r'System', out, re.MULTILINE)
-    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 == ''
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/tunnel.html b/docs/meshtastic/tunnel.html deleted file mode 100644 index 27414d5..0000000 --- a/docs/meshtastic/tunnel.html +++ /dev/null @@ -1,615 +0,0 @@ - - - - - - -meshtastic.tunnel API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.tunnel

-
-
-

Code for IP tunnel over a mesh

-

Note python-pytuntap was too buggy

-

using pip3 install pytap2

-

make sure to "sudo setcap cap_net_admin+eip /usr/bin/python3.8" so python can access tun device without being root

-

sudo ip tuntap del mode tun tun0

-

sudo bin/run.sh –port /dev/ttyUSB0 –setch-shortfast

-

sudo bin/run.sh –port /dev/ttyUSB0 –tunnel –debug

-

ssh -Y root@192.168.10.151 (or dietpi), default password p

-

ncat -e /bin/cat -k -u -l 1235

-

ncat -u 10.115.64.152 1235

-

ping -c 1 -W 20 10.115.64.152

-

ping -i 30 -W 30 10.115.64.152

-

FIXME: use a more optimal MTU

-
- -Expand source code - -
"""Code for IP tunnel over a mesh
-
-# Note python-pytuntap was too buggy
-# using pip3 install pytap2
-# make sure to "sudo setcap cap_net_admin+eip /usr/bin/python3.8" so python can access tun device without being root
-# sudo ip tuntap del mode tun tun0
-# sudo bin/run.sh --port /dev/ttyUSB0 --setch-shortfast
-# sudo bin/run.sh --port /dev/ttyUSB0 --tunnel --debug
-# ssh -Y root@192.168.10.151 (or dietpi), default password p
-# ncat -e /bin/cat -k -u -l 1235
-# ncat -u 10.115.64.152 1235
-# ping -c 1 -W 20 10.115.64.152
-# ping -i 30 -W 30 10.115.64.152
-
-# FIXME: use a more optimal MTU
-"""
-
-import logging
-import threading
-from pubsub import pub
-
-from pytap2 import TapDevice
-
-from . import portnums_pb2
-
-# A new non standard log level that is lower level than DEBUG
-LOG_TRACE = 5
-
-# fixme - find a way to move onTunnelReceive inside of the class
-tunnelInstance = None
-
-"""A list of chatty UDP services we should never accidentally
-forward to our slow network"""
-udpBlacklist = {
-    1900,  # SSDP
-    5353,  # multicast DNS
-}
-
-"""A list of TCP services to block"""
-tcpBlacklist = {}
-
-"""A list of protocols we ignore"""
-protocolBlacklist = {
-    0x02,  # IGMP
-    0x80,  # Service-Specific Connection-Oriented Protocol in a Multilink and Connectionless Environment
-}
-
-
-def hexstr(barray):
-    """Print a string of hex digits"""
-    return ":".join('{:02x}'.format(x) for x in barray)
-
-
-def ipstr(barray):
-    """Print a string of ip digits"""
-    return ".".join('{}'.format(x) for x in barray)
-
-
-def readnet_u16(p, offset):
-    """Read big endian u16 (network byte order)"""
-    return p[offset] * 256 + p[offset + 1]
-
-
-def onTunnelReceive(packet, interface):
-    """Callback for received tunneled messages from mesh
-
-    FIXME figure out how to do closures with methods in python"""
-    tunnelInstance.onReceive(packet)
-
-
-class Tunnel:
-    """A TUN based IP tunnel over meshtastic"""
-
-    def __init__(self, iface, subnet=None, netmask="255.255.0.0"):
-        """
-        Constructor
-
-        iface is the already open MeshInterface instance
-        subnet is used to construct our network number (normally 10.115.x.x)
-        """
-
-        if subnet is None:
-            subnet = "10.115"
-
-        self.iface = iface
-        self.subnetPrefix = subnet
-
-        global tunnelInstance
-        tunnelInstance = self
-
-        logging.info("Starting IP to mesh tunnel (you must be root for this *pre-alpha* "\
-                     "feature to work).  Mesh members:")
-
-        pub.subscribe(onTunnelReceive, "meshtastic.receive.data.IP_TUNNEL_APP")
-        myAddr = self._nodeNumToIp(self.iface.myInfo.my_node_num)
-
-        for node in self.iface.nodes.values():
-            nodeId = node["user"]["id"]
-            ip = self._nodeNumToIp(node["num"])
-            logging.info(f"Node { nodeId } has IP address { ip }")
-
-        logging.debug("creating TUN device with MTU=200")
-        # FIXME - figure out real max MTU, it should be 240 - the overhead bytes for SubPacket and Data
-        self.tun = TapDevice(name="mesh")
-        self.tun.up()
-        self.tun.ifconfig(address=myAddr, netmask=netmask, mtu=200)
-        logging.debug(f"starting TUN reader, our IP address is {myAddr}")
-        self._rxThread = threading.Thread(
-            target=self.__tunReader, args=(), daemon=True)
-        self._rxThread.start()
-
-    def onReceive(self, packet):
-        """onReceive"""
-        p = packet["decoded"]["payload"]
-        if packet["from"] == self.iface.myInfo.my_node_num:
-            logging.debug("Ignoring message we sent")
-        else:
-            logging.debug(
-                f"Received mesh tunnel message type={type(p)} len={len(p)}")
-            # we don't really need to check for filtering here (sender should have checked),
-            # but this provides useful debug printing on types of packets received
-            if not self._shouldFilterPacket(p):
-                self.tun.write(p)
-
-    def _shouldFilterPacket(self, p):
-        """Given a packet, decode it and return true if it should be ignored"""
-        protocol = p[8 + 1]
-        srcaddr = p[12:16]
-        destAddr = p[16:20]
-        subheader = 20
-        ignore = False  # Assume we will be forwarding the packet
-        if protocol in protocolBlacklist:
-            ignore = True
-            logging.log(
-                LOG_TRACE, f"Ignoring blacklisted protocol 0x{protocol:02x}")
-        elif protocol == 0x01:  # ICMP
-            icmpType = p[20]
-            icmpCode = p[21]
-            checksum = p[22:24]
-            # pylint: disable=line-too-long
-            logging.debug(f"forwarding ICMP message src={ipstr(srcaddr)}, dest={ipstr(destAddr)}, type={icmpType}, code={icmpCode}, checksum={checksum}")
-            # reply to pings (swap src and dest but keep rest of packet unchanged)
-            #pingback = p[:12]+p[16:20]+p[12:16]+p[20:]
-            # tap.write(pingback)
-        elif protocol == 0x11:  # UDP
-            srcport = readnet_u16(p, subheader)
-            destport = readnet_u16(p, subheader + 2)
-            if destport in udpBlacklist:
-                ignore = True
-                logging.log(
-                    LOG_TRACE, f"ignoring blacklisted UDP port {destport}")
-            else:
-                logging.debug(
-                    f"forwarding udp srcport={srcport}, destport={destport}")
-        elif protocol == 0x06:  # TCP
-            srcport = readnet_u16(p, subheader)
-            destport = readnet_u16(p, subheader + 2)
-            if destport in tcpBlacklist:
-                ignore = True
-                logging.log(LOG_TRACE, f"ignoring blacklisted TCP port {destport}")
-            else:
-                logging.debug(f"forwarding tcp srcport={srcport}, destport={destport}")
-        else:
-            logging.warning(f"forwarding unexpected protocol 0x{protocol:02x}, "\
-                             "src={ipstr(srcaddr)}, dest={ipstr(destAddr)}")
-
-        return ignore
-
-    def __tunReader(self):
-        tap = self.tun
-        logging.debug("TUN reader running")
-        while True:
-            p = tap.read()
-            #logging.debug(f"IP packet received on TUN interface, type={type(p)}")
-            destAddr = p[16:20]
-
-            if not self._shouldFilterPacket(p):
-                self.sendPacket(destAddr, p)
-
-    def _ipToNodeId(self, ipAddr):
-        # We only consider the last 16 bits of the nodenum for IP address matching
-        ipBits = ipAddr[2] * 256 + ipAddr[3]
-
-        if ipBits == 0xffff:
-            return "^all"
-
-        for node in self.iface.nodes.values():
-            nodeNum = node["num"] & 0xffff
-            # logging.debug(f"Considering nodenum 0x{nodeNum:x} for ipBits 0x{ipBits:x}")
-            if (nodeNum) == ipBits:
-                return node["user"]["id"]
-        return None
-
-    def _nodeNumToIp(self, nodeNum):
-        return f"{self.subnetPrefix}.{(nodeNum >> 8) & 0xff}.{nodeNum & 0xff}"
-
-    def sendPacket(self, destAddr, p):
-        """Forward the provided IP packet into the mesh"""
-        nodeId = self._ipToNodeId(destAddr)
-        if nodeId is not None:
-            logging.debug(f"Forwarding packet bytelen={len(p)} dest={ipstr(destAddr)}, destNode={nodeId}")
-            self.iface.sendData(
-                p, nodeId, portnums_pb2.IP_TUNNEL_APP, wantAck=False)
-        else:
-            logging.warning(f"Dropping packet because no node found for destIP={ipstr(destAddr)}")
-
-    def close(self):
-        """Close"""
-        self.tun.close()
-
-
-
-
-
-

Global variables

-
-
var tcpBlacklist
-
-

A list of protocols we ignore

-
-
var tunnelInstance
-
-

A list of chatty UDP services we should never accidentally -forward to our slow network

-
-
var udpBlacklist
-
-

A list of TCP services to block

-
-
-
-
-

Functions

-
-
-def hexstr(barray) -
-
-

Print a string of hex digits

-
- -Expand source code - -
def hexstr(barray):
-    """Print a string of hex digits"""
-    return ":".join('{:02x}'.format(x) for x in barray)
-
-
-
-def ipstr(barray) -
-
-

Print a string of ip digits

-
- -Expand source code - -
def ipstr(barray):
-    """Print a string of ip digits"""
-    return ".".join('{}'.format(x) for x in barray)
-
-
-
-def onTunnelReceive(packet, interface) -
-
-

Callback for received tunneled messages from mesh

-

FIXME figure out how to do closures with methods in python

-
- -Expand source code - -
def onTunnelReceive(packet, interface):
-    """Callback for received tunneled messages from mesh
-
-    FIXME figure out how to do closures with methods in python"""
-    tunnelInstance.onReceive(packet)
-
-
-
-def readnet_u16(p, offset) -
-
-

Read big endian u16 (network byte order)

-
- -Expand source code - -
def readnet_u16(p, offset):
-    """Read big endian u16 (network byte order)"""
-    return p[offset] * 256 + p[offset + 1]
-
-
-
-
-
-

Classes

-
-
-class Tunnel -(iface, subnet=None, netmask='255.255.0.0') -
-
-

A TUN based IP tunnel over meshtastic

-

Constructor

-

iface is the already open MeshInterface instance -subnet is used to construct our network number (normally 10.115.x.x)

-
- -Expand source code - -
class Tunnel:
-    """A TUN based IP tunnel over meshtastic"""
-
-    def __init__(self, iface, subnet=None, netmask="255.255.0.0"):
-        """
-        Constructor
-
-        iface is the already open MeshInterface instance
-        subnet is used to construct our network number (normally 10.115.x.x)
-        """
-
-        if subnet is None:
-            subnet = "10.115"
-
-        self.iface = iface
-        self.subnetPrefix = subnet
-
-        global tunnelInstance
-        tunnelInstance = self
-
-        logging.info("Starting IP to mesh tunnel (you must be root for this *pre-alpha* "\
-                     "feature to work).  Mesh members:")
-
-        pub.subscribe(onTunnelReceive, "meshtastic.receive.data.IP_TUNNEL_APP")
-        myAddr = self._nodeNumToIp(self.iface.myInfo.my_node_num)
-
-        for node in self.iface.nodes.values():
-            nodeId = node["user"]["id"]
-            ip = self._nodeNumToIp(node["num"])
-            logging.info(f"Node { nodeId } has IP address { ip }")
-
-        logging.debug("creating TUN device with MTU=200")
-        # FIXME - figure out real max MTU, it should be 240 - the overhead bytes for SubPacket and Data
-        self.tun = TapDevice(name="mesh")
-        self.tun.up()
-        self.tun.ifconfig(address=myAddr, netmask=netmask, mtu=200)
-        logging.debug(f"starting TUN reader, our IP address is {myAddr}")
-        self._rxThread = threading.Thread(
-            target=self.__tunReader, args=(), daemon=True)
-        self._rxThread.start()
-
-    def onReceive(self, packet):
-        """onReceive"""
-        p = packet["decoded"]["payload"]
-        if packet["from"] == self.iface.myInfo.my_node_num:
-            logging.debug("Ignoring message we sent")
-        else:
-            logging.debug(
-                f"Received mesh tunnel message type={type(p)} len={len(p)}")
-            # we don't really need to check for filtering here (sender should have checked),
-            # but this provides useful debug printing on types of packets received
-            if not self._shouldFilterPacket(p):
-                self.tun.write(p)
-
-    def _shouldFilterPacket(self, p):
-        """Given a packet, decode it and return true if it should be ignored"""
-        protocol = p[8 + 1]
-        srcaddr = p[12:16]
-        destAddr = p[16:20]
-        subheader = 20
-        ignore = False  # Assume we will be forwarding the packet
-        if protocol in protocolBlacklist:
-            ignore = True
-            logging.log(
-                LOG_TRACE, f"Ignoring blacklisted protocol 0x{protocol:02x}")
-        elif protocol == 0x01:  # ICMP
-            icmpType = p[20]
-            icmpCode = p[21]
-            checksum = p[22:24]
-            # pylint: disable=line-too-long
-            logging.debug(f"forwarding ICMP message src={ipstr(srcaddr)}, dest={ipstr(destAddr)}, type={icmpType}, code={icmpCode}, checksum={checksum}")
-            # reply to pings (swap src and dest but keep rest of packet unchanged)
-            #pingback = p[:12]+p[16:20]+p[12:16]+p[20:]
-            # tap.write(pingback)
-        elif protocol == 0x11:  # UDP
-            srcport = readnet_u16(p, subheader)
-            destport = readnet_u16(p, subheader + 2)
-            if destport in udpBlacklist:
-                ignore = True
-                logging.log(
-                    LOG_TRACE, f"ignoring blacklisted UDP port {destport}")
-            else:
-                logging.debug(
-                    f"forwarding udp srcport={srcport}, destport={destport}")
-        elif protocol == 0x06:  # TCP
-            srcport = readnet_u16(p, subheader)
-            destport = readnet_u16(p, subheader + 2)
-            if destport in tcpBlacklist:
-                ignore = True
-                logging.log(LOG_TRACE, f"ignoring blacklisted TCP port {destport}")
-            else:
-                logging.debug(f"forwarding tcp srcport={srcport}, destport={destport}")
-        else:
-            logging.warning(f"forwarding unexpected protocol 0x{protocol:02x}, "\
-                             "src={ipstr(srcaddr)}, dest={ipstr(destAddr)}")
-
-        return ignore
-
-    def __tunReader(self):
-        tap = self.tun
-        logging.debug("TUN reader running")
-        while True:
-            p = tap.read()
-            #logging.debug(f"IP packet received on TUN interface, type={type(p)}")
-            destAddr = p[16:20]
-
-            if not self._shouldFilterPacket(p):
-                self.sendPacket(destAddr, p)
-
-    def _ipToNodeId(self, ipAddr):
-        # We only consider the last 16 bits of the nodenum for IP address matching
-        ipBits = ipAddr[2] * 256 + ipAddr[3]
-
-        if ipBits == 0xffff:
-            return "^all"
-
-        for node in self.iface.nodes.values():
-            nodeNum = node["num"] & 0xffff
-            # logging.debug(f"Considering nodenum 0x{nodeNum:x} for ipBits 0x{ipBits:x}")
-            if (nodeNum) == ipBits:
-                return node["user"]["id"]
-        return None
-
-    def _nodeNumToIp(self, nodeNum):
-        return f"{self.subnetPrefix}.{(nodeNum >> 8) & 0xff}.{nodeNum & 0xff}"
-
-    def sendPacket(self, destAddr, p):
-        """Forward the provided IP packet into the mesh"""
-        nodeId = self._ipToNodeId(destAddr)
-        if nodeId is not None:
-            logging.debug(f"Forwarding packet bytelen={len(p)} dest={ipstr(destAddr)}, destNode={nodeId}")
-            self.iface.sendData(
-                p, nodeId, portnums_pb2.IP_TUNNEL_APP, wantAck=False)
-        else:
-            logging.warning(f"Dropping packet because no node found for destIP={ipstr(destAddr)}")
-
-    def close(self):
-        """Close"""
-        self.tun.close()
-
-

Methods

-
-
-def close(self) -
-
-

Close

-
- -Expand source code - -
def close(self):
-    """Close"""
-    self.tun.close()
-
-
-
-def onReceive(self, packet) -
-
-

onReceive

-
- -Expand source code - -
def onReceive(self, packet):
-    """onReceive"""
-    p = packet["decoded"]["payload"]
-    if packet["from"] == self.iface.myInfo.my_node_num:
-        logging.debug("Ignoring message we sent")
-    else:
-        logging.debug(
-            f"Received mesh tunnel message type={type(p)} len={len(p)}")
-        # we don't really need to check for filtering here (sender should have checked),
-        # but this provides useful debug printing on types of packets received
-        if not self._shouldFilterPacket(p):
-            self.tun.write(p)
-
-
-
-def sendPacket(self, destAddr, p) -
-
-

Forward the provided IP packet into the mesh

-
- -Expand source code - -
def sendPacket(self, destAddr, p):
-    """Forward the provided IP packet into the mesh"""
-    nodeId = self._ipToNodeId(destAddr)
-    if nodeId is not None:
-        logging.debug(f"Forwarding packet bytelen={len(p)} dest={ipstr(destAddr)}, destNode={nodeId}")
-        self.iface.sendData(
-            p, nodeId, portnums_pb2.IP_TUNNEL_APP, wantAck=False)
-    else:
-        logging.warning(f"Dropping packet because no node found for destIP={ipstr(destAddr)}")
-
-
-
-
-
-
-
- -
- - - \ No newline at end of file diff --git a/docs/meshtastic/util.html b/docs/meshtastic/util.html deleted file mode 100644 index d7cb08b..0000000 --- a/docs/meshtastic/util.html +++ /dev/null @@ -1,688 +0,0 @@ - - - - - - -meshtastic.util API documentation - - - - - - - - - - - -
-
-
-

Module meshtastic.util

-
-
-

Utility functions.

-
- -Expand source code - -
"""Utility functions.
-"""
-import traceback
-from queue import Queue
-import os
-import sys
-import time
-import platform
-import logging
-import threading
-import serial
-import serial.tools.list_ports
-import pkg_resources
-
-"""Some devices such as a seger jlink we never want to accidentally open"""
-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)
-
-
-def fromPSK(valstr):
-    """A special version of fromStr that assumes the user is trying to set a PSK.
-    In that case we also allow "none", "default" or "random" (to have python generate one), or simpleN
-    """
-    if valstr == "random":
-        return genPSK256()
-    elif valstr == "none":
-        return bytes([0])  # Use the 'no encryption' PSK
-    elif valstr == "default":
-        return bytes([1])  # Use default channel psk
-    elif valstr.startswith("simple"):
-        # Use one of the single byte encodings
-        return bytes([int(valstr[6:]) + 1])
-    else:
-        return fromStr(valstr)
-
-
-def fromStr(valstr):
-    """Try to parse as int, float or bool (and fallback to a string as last resort)
-
-    Returns: an int, bool, float, str or byte array (for strings of hex digits)
-
-    Args:
-        valstr (string): A user provided string
-    """
-    if len(valstr) == 0:  # Treat an emptystring as an empty bytes
-        val = bytes()
-    elif valstr.startswith('0x'):
-        # if needed convert to string with asBytes.decode('utf-8')
-        val = bytes.fromhex(valstr[2:])
-    elif valstr.lower() in {"t", "true", "yes"}:
-        val = True
-    elif valstr.lower() in {"f", "false", "no"}:
-        val = False
-    else:
-        try:
-            val = int(valstr)
-        except ValueError:
-            try:
-                val = float(valstr)
-            except ValueError:
-                val = valstr  # Not a float or an int, assume string
-    return val
-
-
-def pskToString(psk: bytes):
-    """Given an array of PSK bytes, decode them into a human readable (but privacy protecting) string"""
-    if len(psk) == 0:
-        return "unencrypted"
-    elif len(psk) == 1:
-        b = psk[0]
-        if b == 0:
-            return "unencrypted"
-        elif b == 1:
-            return "default"
-        else:
-            return f"simple{b - 1}"
-    else:
-        return "secret"
-
-
-def stripnl(s):
-    """Remove newlines from a string (and remove extra whitespace)"""
-    s = str(s).replace("\n", " ")
-    return ' '.join(s.split())
-
-
-def fixme(message):
-    """Raise an exception for things that needs to be fixed"""
-    raise Exception(f"FIXME: {message}")
-
-
-def catchAndIgnore(reason, closure):
-    """Call a closure but if it throws an exception print it and continue"""
-    try:
-        closure()
-    except BaseException as ex:
-        logging.error(f"Exception thrown in {reason}: {ex}")
-
-
-def findPorts():
-    """Find all ports that might have meshtastic devices
-
-    Returns:
-        list -- a list of device paths
-    """
-    l = list(map(lambda port: port.device,
-                 filter(lambda port: port.vid is not None and port.vid not in blacklistVids,
-                        serial.tools.list_ports.comports())))
-    l.sort()
-    return l
-
-
-class dotdict(dict):
-    """dot.notation access to dictionary attributes"""
-    __getattr__ = dict.get
-    __setattr__ = dict.__setitem__
-    __delattr__ = dict.__delitem__
-
-
-class Timeout:
-    """Timeout class"""
-    def __init__(self, maxSecs=20):
-        self.expireTime = 0
-        self.sleepInterval = 0.1
-        self.expireTimeout = maxSecs
-
-    def reset(self):
-        """Restart the waitForSet timer"""
-        self.expireTime = time.time() + self.expireTimeout
-
-    def waitForSet(self, target, attrs=()):
-        """Block until the specified attributes are set. Returns True if config has been received."""
-        self.reset()
-        while time.time() < self.expireTime:
-            if all(map(lambda a: getattr(target, a, None), attrs)):
-                return True
-            time.sleep(self.sleepInterval)
-        return False
-
-
-class DeferredExecution():
-    """A thread that accepts closures to run, and runs them as they are received"""
-
-    def __init__(self, name=None):
-        self.queue = Queue()
-        self.thread = threading.Thread(target=self._run, args=(), name=name)
-        self.thread.daemon = True
-        self.thread.start()
-
-    def queueWork(self, runnable):
-        """ Queue up the work"""
-        self.queue.put(runnable)
-
-    def _run(self):
-        while True:
-            try:
-                o = self.queue.get()
-                o()
-            except:
-                logging.error(
-                    f"Unexpected error in deferred execution {sys.exc_info()[0]}")
-                print(traceback.format_exc())
-
-
-def our_exit(message, return_value = 1):
-    """Print the message and return a value.
-       return_value defaults to 1 (non-successful)
-    """
-    print(message)
-    sys.exit(return_value)
-
-
-def support_info():
-    """Print out info that helps troubleshooting of the cli."""
-    print('')
-    print('If having issues with meshtastic cli or python library')
-    print('or wish to make feature requests, visit:')
-    print('https://github.com/meshtastic/Meshtastic-python/issues')
-    print('When adding an issue, be sure to include the following info:')
-    print(' System: {0}'.format(platform.system()))
-    print('   Platform: {0}'.format(platform.platform()))
-    print('   Release: {0}'.format(platform.uname().release))
-    print('   Machine: {0}'.format(platform.uname().machine))
-    print('   Encoding (stdin): {0}'.format(sys.stdin.encoding))
-    print('   Encoding (stdout): {0}'.format(sys.stdout.encoding))
-    print(' meshtastic: v{0}'.format(pkg_resources.require('meshtastic')[0].version))
-    print(' Executable: {0}'.format(sys.argv[0]))
-    print(' Python: {0} {1} {2}'.format(platform.python_version(),
-          platform.python_implementation(), platform.python_compiler()))
-    print('')
-    print('Please add the output from the command: meshtastic --info')
-
-
-
-
-
-
-
-

Functions

-
-
-def catchAndIgnore(reason, closure) -
-
-

Call a closure but if it throws an exception print it and continue

-
- -Expand source code - -
def catchAndIgnore(reason, closure):
-    """Call a closure but if it throws an exception print it and continue"""
-    try:
-        closure()
-    except BaseException as ex:
-        logging.error(f"Exception thrown in {reason}: {ex}")
-
-
-
-def findPorts() -
-
-

Find all ports that might have meshtastic devices

-

Returns

-

list – a list of device paths

-
- -Expand source code - -
def findPorts():
-    """Find all ports that might have meshtastic devices
-
-    Returns:
-        list -- a list of device paths
-    """
-    l = list(map(lambda port: port.device,
-                 filter(lambda port: port.vid is not None and port.vid not in blacklistVids,
-                        serial.tools.list_ports.comports())))
-    l.sort()
-    return l
-
-
-
-def fixme(message) -
-
-

Raise an exception for things that needs to be fixed

-
- -Expand source code - -
def fixme(message):
-    """Raise an exception for things that needs to be fixed"""
-    raise Exception(f"FIXME: {message}")
-
-
-
-def fromPSK(valstr) -
-
-

A special version of fromStr that assumes the user is trying to set a PSK. -In that case we also allow "none", "default" or "random" (to have python generate one), or simpleN

-
- -Expand source code - -
def fromPSK(valstr):
-    """A special version of fromStr that assumes the user is trying to set a PSK.
-    In that case we also allow "none", "default" or "random" (to have python generate one), or simpleN
-    """
-    if valstr == "random":
-        return genPSK256()
-    elif valstr == "none":
-        return bytes([0])  # Use the 'no encryption' PSK
-    elif valstr == "default":
-        return bytes([1])  # Use default channel psk
-    elif valstr.startswith("simple"):
-        # Use one of the single byte encodings
-        return bytes([int(valstr[6:]) + 1])
-    else:
-        return fromStr(valstr)
-
-
-
-def fromStr(valstr) -
-
-

Try to parse as int, float or bool (and fallback to a string as last resort)

-

Returns: an int, bool, float, str or byte array (for strings of hex digits)

-

Args

-
-
valstr : string
-
A user provided string
-
-
- -Expand source code - -
def fromStr(valstr):
-    """Try to parse as int, float or bool (and fallback to a string as last resort)
-
-    Returns: an int, bool, float, str or byte array (for strings of hex digits)
-
-    Args:
-        valstr (string): A user provided string
-    """
-    if len(valstr) == 0:  # Treat an emptystring as an empty bytes
-        val = bytes()
-    elif valstr.startswith('0x'):
-        # if needed convert to string with asBytes.decode('utf-8')
-        val = bytes.fromhex(valstr[2:])
-    elif valstr.lower() in {"t", "true", "yes"}:
-        val = True
-    elif valstr.lower() in {"f", "false", "no"}:
-        val = False
-    else:
-        try:
-            val = int(valstr)
-        except ValueError:
-            try:
-                val = float(valstr)
-            except ValueError:
-                val = valstr  # Not a float or an int, assume string
-    return val
-
-
-
-def genPSK256() -
-
-

Generate a random preshared key

-
- -Expand source code - -
def genPSK256():
-    """Generate a random preshared key"""
-    return os.urandom(32)
-
-
-
-def our_exit(message, return_value=1) -
-
-

Print the message and return a value. -return_value defaults to 1 (non-successful)

-
- -Expand source code - -
def our_exit(message, return_value = 1):
-    """Print the message and return a value.
-       return_value defaults to 1 (non-successful)
-    """
-    print(message)
-    sys.exit(return_value)
-
-
-
-def pskToString(psk: bytes) -
-
-

Given an array of PSK bytes, decode them into a human readable (but privacy protecting) string

-
- -Expand source code - -
def pskToString(psk: bytes):
-    """Given an array of PSK bytes, decode them into a human readable (but privacy protecting) string"""
-    if len(psk) == 0:
-        return "unencrypted"
-    elif len(psk) == 1:
-        b = psk[0]
-        if b == 0:
-            return "unencrypted"
-        elif b == 1:
-            return "default"
-        else:
-            return f"simple{b - 1}"
-    else:
-        return "secret"
-
-
-
-def quoteBooleans(a_string) -
-
-

Quote booleans -given a string that contains ": true", replace with ": 'true'" (or false)

-
- -Expand source code - -
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 stripnl(s) -
-
-

Remove newlines from a string (and remove extra whitespace)

-
- -Expand source code - -
def stripnl(s):
-    """Remove newlines from a string (and remove extra whitespace)"""
-    s = str(s).replace("\n", " ")
-    return ' '.join(s.split())
-
-
-
-def support_info() -
-
-

Print out info that helps troubleshooting of the cli.

-
- -Expand source code - -
def support_info():
-    """Print out info that helps troubleshooting of the cli."""
-    print('')
-    print('If having issues with meshtastic cli or python library')
-    print('or wish to make feature requests, visit:')
-    print('https://github.com/meshtastic/Meshtastic-python/issues')
-    print('When adding an issue, be sure to include the following info:')
-    print(' System: {0}'.format(platform.system()))
-    print('   Platform: {0}'.format(platform.platform()))
-    print('   Release: {0}'.format(platform.uname().release))
-    print('   Machine: {0}'.format(platform.uname().machine))
-    print('   Encoding (stdin): {0}'.format(sys.stdin.encoding))
-    print('   Encoding (stdout): {0}'.format(sys.stdout.encoding))
-    print(' meshtastic: v{0}'.format(pkg_resources.require('meshtastic')[0].version))
-    print(' Executable: {0}'.format(sys.argv[0]))
-    print(' Python: {0} {1} {2}'.format(platform.python_version(),
-          platform.python_implementation(), platform.python_compiler()))
-    print('')
-    print('Please add the output from the command: meshtastic --info')
-
-
-
-
-
-

Classes

-
-
-class DeferredExecution -(name=None) -
-
-

A thread that accepts closures to run, and runs them as they are received

-
- -Expand source code - -
class DeferredExecution():
-    """A thread that accepts closures to run, and runs them as they are received"""
-
-    def __init__(self, name=None):
-        self.queue = Queue()
-        self.thread = threading.Thread(target=self._run, args=(), name=name)
-        self.thread.daemon = True
-        self.thread.start()
-
-    def queueWork(self, runnable):
-        """ Queue up the work"""
-        self.queue.put(runnable)
-
-    def _run(self):
-        while True:
-            try:
-                o = self.queue.get()
-                o()
-            except:
-                logging.error(
-                    f"Unexpected error in deferred execution {sys.exc_info()[0]}")
-                print(traceback.format_exc())
-
-

Methods

-
-
-def queueWork(self, runnable) -
-
-

Queue up the work

-
- -Expand source code - -
def queueWork(self, runnable):
-    """ Queue up the work"""
-    self.queue.put(runnable)
-
-
-
-
-
-class Timeout -(maxSecs=20) -
-
-

Timeout class

-
- -Expand source code - -
class Timeout:
-    """Timeout class"""
-    def __init__(self, maxSecs=20):
-        self.expireTime = 0
-        self.sleepInterval = 0.1
-        self.expireTimeout = maxSecs
-
-    def reset(self):
-        """Restart the waitForSet timer"""
-        self.expireTime = time.time() + self.expireTimeout
-
-    def waitForSet(self, target, attrs=()):
-        """Block until the specified attributes are set. Returns True if config has been received."""
-        self.reset()
-        while time.time() < self.expireTime:
-            if all(map(lambda a: getattr(target, a, None), attrs)):
-                return True
-            time.sleep(self.sleepInterval)
-        return False
-
-

Methods

-
-
-def reset(self) -
-
-

Restart the waitForSet timer

-
- -Expand source code - -
def reset(self):
-    """Restart the waitForSet timer"""
-    self.expireTime = time.time() + self.expireTimeout
-
-
-
-def waitForSet(self, target, attrs=()) -
-
-

Block until the specified attributes are set. Returns True if config has been received.

-
- -Expand source code - -
def waitForSet(self, target, attrs=()):
-    """Block until the specified attributes are set. Returns True if config has been received."""
-    self.reset()
-    while time.time() < self.expireTime:
-        if all(map(lambda a: getattr(target, a, None), attrs)):
-            return True
-        time.sleep(self.sleepInterval)
-    return False
-
-
-
-
-
-class dotdict -(*args, **kwargs) -
-
-

dot.notation access to dictionary attributes

-
- -Expand source code - -
class dotdict(dict):
-    """dot.notation access to dictionary attributes"""
-    __getattr__ = dict.get
-    __setattr__ = dict.__setitem__
-    __delattr__ = dict.__delitem__
-
-

Ancestors

-
    -
  • builtins.dict
  • -
-
-
-
-
- -
- - - \ No newline at end of file