This commit is contained in:
Kevin Hester
2021-03-18 19:43:10 +08:00
parent 719425b833
commit 6472beccc5
7 changed files with 309 additions and 68 deletions

View File

@@ -51,7 +51,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax='proto3',
serialized_options=b'\n\023com.geeksville.meshB\013AdminProtosH\003',
create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x0b\x61\x64min.proto\x1a\nmesh.proto\x1a\x11radioconfig.proto\x1a\rchannel.proto\"\xc7\x02\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\x1d\n\x13\x63onfirm_set_channel\x18 \x01(\x08H\x00\x12\x1b\n\x11\x63onfirm_set_radio\x18! \x01(\x08H\x00\x42\t\n\x07variantB$\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosH\x03\x62\x06proto3'
serialized_pb=b'\n\x0b\x61\x64min.proto\x1a\nmesh.proto\x1a\x11radioconfig.proto\x1a\rchannel.proto\"\xe1\x02\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\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\x42\t\n\x07variantB$\n\x13\x63om.geeksville.meshB\x0b\x41\x64minProtosH\x03\x62\x06proto3'
,
dependencies=[mesh__pb2.DESCRIPTOR,radioconfig__pb2.DESCRIPTOR,channel__pb2.DESCRIPTOR,])
@@ -129,6 +129,13 @@ _ADMINMESSAGE = _descriptor.Descriptor(
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='exit_simulator', full_name='AdminMessage.exit_simulator', index=9,
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, create_key=_descriptor._internal_create_key),
],
extensions=[
],
@@ -147,7 +154,7 @@ _ADMINMESSAGE = _descriptor.Descriptor(
fields=[]),
],
serialized_start=62,
serialized_end=389,
serialized_end=415,
)
_ADMINMESSAGE.fields_by_name['set_radio'].message_type = radioconfig__pb2._RADIOCONFIG
@@ -182,6 +189,9 @@ _ADMINMESSAGE.fields_by_name['confirm_set_channel'].containing_oneof = _
_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']
DESCRIPTOR.message_types_by_name['AdminMessage'] = _ADMINMESSAGE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
@@ -234,6 +244,10 @@ DESCRIPTOR._options = None
<dd>
<div class="desc"><p>Field AdminMessage.confirm_set_radio</p></div>
</dd>
<dt id="meshtastic.admin_pb2.AdminMessage.exit_simulator"><code class="name">var <span class="ident">exit_simulator</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.exit_simulator</p></div>
</dd>
<dt id="meshtastic.admin_pb2.AdminMessage.get_channel_request"><code class="name">var <span class="ident">get_channel_request</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.get_channel_request</p></div>
@@ -286,6 +300,7 @@ DESCRIPTOR._options = None
<li><code><a title="meshtastic.admin_pb2.AdminMessage.DESCRIPTOR" href="#meshtastic.admin_pb2.AdminMessage.DESCRIPTOR">DESCRIPTOR</a></code></li>
<li><code><a title="meshtastic.admin_pb2.AdminMessage.confirm_set_channel" href="#meshtastic.admin_pb2.AdminMessage.confirm_set_channel">confirm_set_channel</a></code></li>
<li><code><a title="meshtastic.admin_pb2.AdminMessage.confirm_set_radio" href="#meshtastic.admin_pb2.AdminMessage.confirm_set_radio">confirm_set_radio</a></code></li>
<li><code><a title="meshtastic.admin_pb2.AdminMessage.exit_simulator" href="#meshtastic.admin_pb2.AdminMessage.exit_simulator">exit_simulator</a></code></li>
<li><code><a title="meshtastic.admin_pb2.AdminMessage.get_channel_request" href="#meshtastic.admin_pb2.AdminMessage.get_channel_request">get_channel_request</a></code></li>
<li><code><a title="meshtastic.admin_pb2.AdminMessage.get_channel_response" href="#meshtastic.admin_pb2.AdminMessage.get_channel_response">get_channel_response</a></code></li>
<li><code><a title="meshtastic.admin_pb2.AdminMessage.get_radio_request" href="#meshtastic.admin_pb2.AdminMessage.get_radio_request">get_radio_request</a></code></li>

View File

@@ -380,6 +380,15 @@ class Node:
wantResponse=True,
onResponse=onResponse)
def exitSimulator(self):
&#34;&#34;&#34;
Tell a simulator node to exit (this message is ignored for other nodes)
&#34;&#34;&#34;
p = admin_pb2.AdminMessage()
p.exit_simulator = True
return self._sendAdmin(p)
def _requestChannel(self, channelNum: int):
&#34;&#34;&#34;
Done with initial config messages, now send regular MeshPackets to ask for settings
@@ -2434,6 +2443,15 @@ wantResponse &ndash; True if you want the service on the other side to send an a
wantResponse=True,
onResponse=onResponse)
def exitSimulator(self):
&#34;&#34;&#34;
Tell a simulator node to exit (this message is ignored for other nodes)
&#34;&#34;&#34;
p = admin_pb2.AdminMessage()
p.exit_simulator = True
return self._sendAdmin(p)
def _requestChannel(self, channelNum: int):
&#34;&#34;&#34;
Done with initial config messages, now send regular MeshPackets to ask for settings
@@ -2515,6 +2533,25 @@ def channelURL(self):
</dl>
<h3>Methods</h3>
<dl>
<dt id="meshtastic.Node.exitSimulator"><code class="name flex">
<span>def <span class="ident">exitSimulator</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Tell a simulator node to exit (this message is ignored for other nodes)</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def exitSimulator(self):
&#34;&#34;&#34;
Tell a simulator node to exit (this message is ignored for other nodes)
&#34;&#34;&#34;
p = admin_pb2.AdminMessage()
p.exit_simulator = True
return self._sendAdmin(p) </code></pre>
</details>
</dd>
<dt id="meshtastic.Node.getChannelByName"><code class="name flex">
<span>def <span class="ident">getChannelByName</span></span>(<span>self, name)</span>
</code></dt>
@@ -3221,6 +3258,7 @@ hostname {string} &ndash; Hostname/IP address of the device to connect to</p></d
<h4><code><a title="meshtastic.Node" href="#meshtastic.Node">Node</a></code></h4>
<ul class="two-column">
<li><code><a title="meshtastic.Node.channelURL" href="#meshtastic.Node.channelURL">channelURL</a></code></li>
<li><code><a title="meshtastic.Node.exitSimulator" href="#meshtastic.Node.exitSimulator">exitSimulator</a></code></li>
<li><code><a title="meshtastic.Node.getChannelByName" href="#meshtastic.Node.getChannelByName">getChannelByName</a></code></li>
<li><code><a title="meshtastic.Node.getDisabledChannel" href="#meshtastic.Node.getDisabledChannel">getDisabledChannel</a></code></li>
<li><code><a title="meshtastic.Node.requestConfig" href="#meshtastic.Node.requestConfig">requestConfig</a></code></li>

View File

File diff suppressed because one or more lines are too long

View File

@@ -29,14 +29,16 @@
<pre><code class="python">from . import portnums_pb2, remote_hardware_pb2
from pubsub import pub
def onGPIOreceive(packet, interface):
&#34;&#34;&#34;Callback for received GPIO responses
FIXME figure out how to do closures with methods in python&#34;&#34;&#34;
pb = remote_hardware_pb2.HardwareMessage()
pb.ParseFromString(packet[&#34;decoded&#34;][&#34;data&#34;][&#34;payload&#34;])
print(f&#34;Received RemoteHardware typ={pb.typ}, gpio_value={pb.gpio_value}&#34;)
class RemoteHardwareClient:
&#34;&#34;&#34;
This is the client code to control/monitor simple hardware built into the
@@ -51,8 +53,17 @@ class RemoteHardwareClient:
iface is the already open MeshInterface instance
&#34;&#34;&#34;
self.iface = iface
ch = iface.localNode.getChannelByName(&#34;gpio&#34;)
if not ch:
raise Exception(
&#34;No gpio channel found, please create before using this (secured) service&#34;)
self.channelIndex = ch.index
pub.subscribe(onGPIOreceive, &#34;meshtastic.receive.data.REMOTE_HARDWARE_APP&#34;)
pub.subscribe(
onGPIOreceive, &#34;meshtastic.receive.data.REMOTE_HARDWARE_APP&#34;)
def _sendHardware(self, nodeid, r):
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck=True, channelIndex=self.channelIndex)
def writeGPIOs(self, nodeid, mask, vals):
&#34;&#34;&#34;
@@ -63,21 +74,21 @@ class RemoteHardwareClient:
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
r.gpio_mask = mask
r.gpio_value = vals
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck = True)
return self._sendHardware(nodeid, r)
def readGPIOs(self, nodeid, mask):
&#34;&#34;&#34;Read the specified bits from GPIO inputs on the device&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
r.gpio_mask = mask
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck = True)
return self._sendHardware(nodeid, r)
def watchGPIOs(self, nodeid, mask):
&#34;&#34;&#34;Watch the specified bits from GPIO inputs on the device for changes&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
r.gpio_mask = mask
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck = True) </code></pre>
return self._sendHardware(nodeid, r)</code></pre>
</details>
</section>
<section>
@@ -99,7 +110,7 @@ class RemoteHardwareClient:
</summary>
<pre><code class="python">def onGPIOreceive(packet, interface):
&#34;&#34;&#34;Callback for received GPIO responses
FIXME figure out how to do closures with methods in python&#34;&#34;&#34;
pb = remote_hardware_pb2.HardwareMessage()
pb.ParseFromString(packet[&#34;decoded&#34;][&#34;data&#34;][&#34;payload&#34;])
@@ -140,8 +151,17 @@ code for how you can connect to your own custom meshtastic services</p>
iface is the already open MeshInterface instance
&#34;&#34;&#34;
self.iface = iface
ch = iface.localNode.getChannelByName(&#34;gpio&#34;)
if not ch:
raise Exception(
&#34;No gpio channel found, please create before using this (secured) service&#34;)
self.channelIndex = ch.index
pub.subscribe(onGPIOreceive, &#34;meshtastic.receive.data.REMOTE_HARDWARE_APP&#34;)
pub.subscribe(
onGPIOreceive, &#34;meshtastic.receive.data.REMOTE_HARDWARE_APP&#34;)
def _sendHardware(self, nodeid, r):
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck=True, channelIndex=self.channelIndex)
def writeGPIOs(self, nodeid, mask, vals):
&#34;&#34;&#34;
@@ -152,21 +172,21 @@ code for how you can connect to your own custom meshtastic services</p>
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
r.gpio_mask = mask
r.gpio_value = vals
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck = True)
return self._sendHardware(nodeid, r)
def readGPIOs(self, nodeid, mask):
&#34;&#34;&#34;Read the specified bits from GPIO inputs on the device&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
r.gpio_mask = mask
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck = True)
return self._sendHardware(nodeid, r)
def watchGPIOs(self, nodeid, mask):
&#34;&#34;&#34;Watch the specified bits from GPIO inputs on the device for changes&#34;&#34;&#34;
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
r.gpio_mask = mask
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck = True) </code></pre>
return self._sendHardware(nodeid, r)</code></pre>
</details>
<h3>Methods</h3>
<dl>
@@ -184,7 +204,7 @@ code for how you can connect to your own custom meshtastic services</p>
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
r.gpio_mask = mask
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck = True)</code></pre>
return self._sendHardware(nodeid, r)</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware.RemoteHardwareClient.watchGPIOs"><code class="name flex">
@@ -201,7 +221,7 @@ code for how you can connect to your own custom meshtastic services</p>
r = remote_hardware_pb2.HardwareMessage()
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
r.gpio_mask = mask
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck = True) </code></pre>
return self._sendHardware(nodeid, r)</code></pre>
</details>
</dd>
<dt id="meshtastic.remote_hardware.RemoteHardwareClient.writeGPIOs"><code class="name flex">
@@ -224,7 +244,7 @@ are 1 will be changed</p></div>
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
r.gpio_mask = mask
r.gpio_value = vals
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP, wantAck = True)</code></pre>
return self._sendHardware(nodeid, r)</code></pre>
</details>
</dd>
</dl>

View File

@@ -28,7 +28,7 @@
</summary>
<pre><code class="python">import logging
from . import util
from . import SerialInterface, BROADCAST_NUM
from . import SerialInterface, TCPInterface, BROADCAST_NUM
from pubsub import pub
import time
import sys
@@ -178,7 +178,26 @@ def testAll():
testThread()
for i in interfaces:
i.close()</code></pre>
i.close()
def testSimulator():
&#34;&#34;&#34;
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 &#39;from meshtastic.test import testSimulator; testSimulator()&#39;
&#34;&#34;&#34;
logging.basicConfig(level=logging.DEBUG if False else logging.INFO)
logging.info(&#34;Connecting to simulator on localhost!&#34;)
iface = TCPInterface(&#34;localhost&#34;)
iface.showInfo()
iface.localNode.showInfo()
iface.localNode.exitSimulator()
iface.close()
logging.info(&#34;Integration test successful!&#34;)
sys.exit(0)</code></pre>
</details>
</section>
<section>
@@ -405,6 +424,39 @@ toInterface {[type]} &ndash; [description]</p>
return False # Failed to send</code></pre>
</details>
</dd>
<dt id="meshtastic.test.testSimulator"><code class="name flex">
<span>def <span class="ident">testSimulator</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>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.</p>
<p>Run with
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def testSimulator():
&#34;&#34;&#34;
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 &#39;from meshtastic.test import testSimulator; testSimulator()&#39;
&#34;&#34;&#34;
logging.basicConfig(level=logging.DEBUG if False else logging.INFO)
logging.info(&#34;Connecting to simulator on localhost!&#34;)
iface = TCPInterface(&#34;localhost&#34;)
iface.showInfo()
iface.localNode.showInfo()
iface.localNode.exitSimulator()
iface.close()
logging.info(&#34;Integration test successful!&#34;)
sys.exit(0)</code></pre>
</details>
</dd>
<dt id="meshtastic.test.testThread"><code class="name flex">
<span>def <span class="ident">testThread</span></span>(<span>numTests=50)</span>
</code></dt>
@@ -451,6 +503,7 @@ toInterface {[type]} &ndash; [description]</p>
<li><code><a title="meshtastic.test.subscribe" href="#meshtastic.test.subscribe">subscribe</a></code></li>
<li><code><a title="meshtastic.test.testAll" href="#meshtastic.test.testAll">testAll</a></code></li>
<li><code><a title="meshtastic.test.testSend" href="#meshtastic.test.testSend">testSend</a></code></li>
<li><code><a title="meshtastic.test.testSimulator" href="#meshtastic.test.testSimulator">testSimulator</a></code></li>
<li><code><a title="meshtastic.test.testThread" href="#meshtastic.test.testThread">testThread</a></code></li>
</ul>
</li>

2
proto

Submodule proto updated: 943c3c24ec...b8c0499f28

View File

@@ -12,7 +12,7 @@ with open("README.md", "r") as fh:
# This call to setup() does all the work
setup(
name="meshtastic",
version="1.2.10",
version="1.2.11",
description="Python API & client shell for talking to Meshtastic devices",
long_description=long_description,
long_description_content_type="text/markdown",