Files
python/docs/meshtastic/tests/test_node.html
2021-12-28 22:10:11 -08:00

2272 lines
100 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.1.dev1+g4aa70de.d20211229" />
<title>meshtastic.tests.test_node API documentation</title>
<meta name="description" content="Meshtastic unit tests for node.py" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>meshtastic.tests.test_node</code></h1>
</header>
<section id="section-intro">
<p>Meshtastic unit tests for node.py</p>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">&#34;&#34;&#34;Meshtastic unit tests for node.py&#34;&#34;&#34;
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):
&#34;&#34;&#34;Test that we can instantiate a Node&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
radioConfig = RadioConfig()
anode.radioConfig = radioConfig
anode.showChannels()
anode.showInfo()
out, err = capsys.readouterr()
assert re.search(r&#39;Preferences&#39;, out)
assert re.search(r&#39;Channels&#39;, out)
assert re.search(r&#39;Primary channel URL&#39;, out)
assert err == &#39;&#39;
@pytest.mark.unit
def test_node_reqquestConfig():
&#34;&#34;&#34;Test run requestConfig&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
amesg = MagicMock(autospec=AdminMessage)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
with patch(&#39;meshtastic.admin_pb2.AdminMessage&#39;, return_value=amesg):
anode = Node(mo, &#39;bar&#39;)
anode.requestConfig()
@pytest.mark.unit
def test_setOwner_and_team(caplog):
&#34;&#34;&#34;Test setOwner&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name =&#39;Test123&#39;, short_name=&#39;123&#39;, team=1)
assert re.search(r&#39;p.set_owner.long_name:Test123:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.short_name:123:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.is_licensed:False&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.team:1&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_setOwner_no_short_name(caplog):
&#34;&#34;&#34;Test setOwner&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name =&#39;Test123&#39;)
assert re.search(r&#39;p.set_owner.long_name:Test123:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.short_name:Tst:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.is_licensed:False&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.team:0&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_setOwner_no_short_name_and_long_name_is_short(caplog):
&#34;&#34;&#34;Test setOwner&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name =&#39;Tnt&#39;)
assert re.search(r&#39;p.set_owner.long_name:Tnt:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.short_name:Tnt:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.is_licensed:False&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.team:0&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_setOwner_no_short_name_and_long_name_has_words(caplog):
&#34;&#34;&#34;Test setOwner&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name =&#39;A B C&#39;, is_licensed=True)
assert re.search(r&#39;p.set_owner.long_name:A B C:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.short_name:ABC:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.is_licensed:True&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.team:0&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_exitSimulator(caplog):
&#34;&#34;&#34;Test exitSimulator&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.exitSimulator()
assert re.search(r&#39;in exitSimulator&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_reboot(caplog):
&#34;&#34;&#34;Test reboot&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.reboot()
assert re.search(r&#39;Telling node to reboot&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_setURL_empty_url():
&#34;&#34;&#34;Test reboot&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with pytest.raises(SystemExit) as pytest_wrapped_e:
anode.setURL(&#39;&#39;)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1
@pytest.mark.unit
def test_setURL_valid_URL(caplog):
&#34;&#34;&#34;Test setURL&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
url = &#34;https://www.meshtastic.org/d/#CgUYAyIBAQ&#34;
with caplog.at_level(logging.DEBUG):
anode = Node(iface, &#39;bar&#39;, noProto=True)
anode.radioConfig = &#39;baz&#39;
channels = [&#39;zoo&#39;]
anode.channels = channels
anode.setURL(url)
assert re.search(r&#39;Channel i:0&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;modem_config: Bw125Cr48Sf4096&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;psk: &#34;\\001&#34;&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;role: PRIMARY&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_setURL_valid_URL_but_no_settings(caplog):
&#34;&#34;&#34;Test setURL&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
url = &#34;https://www.meshtastic.org/d/#&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
anode = Node(iface, &#39;bar&#39;, noProto=True)
anode.radioConfig = &#39;baz&#39;
anode.setURL(url)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1
@pytest.mark.unit
def test_showChannels(capsys):
&#34;&#34;&#34;Test showChannels&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
# 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&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;testing&#39;
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&#39;Channels:&#39;, out, re.MULTILINE)
# primary channel
assert re.search(r&#39;Primary channel URL&#39;, out, re.MULTILINE)
assert re.search(r&#39;PRIMARY psk=default &#39;, out, re.MULTILINE)
assert re.search(r&#39;&#34;modemConfig&#34;: &#34;Bw125Cr48Sf4096&#34;&#39;, out, re.MULTILINE)
assert re.search(r&#39;&#34;psk&#34;: &#34;AQ==&#34;&#39;, out, re.MULTILINE)
# secondary channel
assert re.search(r&#39;SECONDARY psk=secret &#39;, out, re.MULTILINE)
assert re.search(r&#39;&#34;psk&#34;: &#34;ipR5DsbJHjWREkCmMKi0M4cA8ksO539Bes31sJAwqDQ=&#34;&#39;, out, re.MULTILINE)
assert err == &#39;&#39;
@pytest.mark.unit
def test_getChannelByChannelIndex():
&#34;&#34;&#34;Test getChannelByChannelIndex()&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
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):
&#34;&#34;&#34;Try to delete primary channel.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
# 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&#39;Warning: Only SECONDARY channels can be deleted&#39;, out, re.MULTILINE)
assert err == &#39;&#39;
@pytest.mark.unit
def test_deleteChannel_secondary():
&#34;&#34;&#34;Try to delete a secondary channel.&#34;&#34;&#34;
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;testing&#39;
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(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, noProto=True)
anode.channels = channels
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;testing&#39;
assert channels[2].settings.name == &#39;&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;
anode.deleteChannel(1)
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;&#39;
assert channels[2].settings.name == &#39;&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;
@pytest.mark.unit
def test_deleteChannel_secondary_with_admin_channel_after_testing():
&#34;&#34;&#34;Try to delete a secondary channel where there is an admin channel.&#34;&#34;&#34;
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;testing&#39;
channel3 = Channel(index=3, role=2)
channel3.settings.name = &#39;admin&#39;
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(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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 == &#39;testing&#39;
assert channels[2].settings.name == &#39;admin&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;
anode.deleteChannel(1)
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;admin&#39;
assert channels[2].settings.name == &#39;&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;
@pytest.mark.unit
def test_deleteChannel_secondary_with_admin_channel_before_testing():
&#34;&#34;&#34;Try to delete a secondary channel where there is an admin channel.&#34;&#34;&#34;
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;admin&#39;
channel3 = Channel(index=3, role=2)
channel3.settings.name = &#39;testing&#39;
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(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, noProto=True)
anode.channels = channels
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;admin&#39;
assert channels[2].settings.name == &#39;testing&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;
anode.deleteChannel(2)
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;admin&#39;
assert channels[2].settings.name == &#39;&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;
@pytest.mark.unit
def test_getChannelByName(capsys):
&#34;&#34;&#34;Get a channel by the name.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;admin&#39;
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(&#39;admin&#39;)
assert ch.index == 2
@pytest.mark.unit
def test_getChannelByName_invalid_name(capsys):
&#34;&#34;&#34;Get a channel by the name but one that is not present.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;admin&#39;
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(&#39;testing&#39;)
assert ch is None
@pytest.mark.unit
def test_getDisabledChannel(capsys):
&#34;&#34;&#34;Get the first disabled channel.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;testingA&#39;
channel3 = Channel(index=3, role=2)
channel3.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel3.settings.name = &#39;testingB&#39;
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):
&#34;&#34;&#34;Get the first disabled channel.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
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):
&#34;&#34;&#34;Get the &#39;admin&#39; channel index.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;admin&#39;
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):
&#34;&#34;&#34;Get the &#39;admin&#39; channel when there is not one.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
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):
&#34;&#34;&#34;Turn off encryption when there is a psk.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
# value from using &#34;--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b &#34;
channel1.settings.psk = b&#39;\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++&#39;
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&#39;Writing modified channels to device&#39;, out)
assert err == &#39;&#39;
@pytest.mark.unit
def test_writeConfig_with_no_radioConfig(capsys):
&#34;&#34;&#34;Test writeConfig with no radioConfig.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, 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&#39;Error: No RadioConfig has been read&#39;, out)
assert err == &#39;&#39;
@pytest.mark.unit
def test_writeConfig(caplog):
&#34;&#34;&#34;Test writeConfig&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
radioConfig = RadioConfig()
anode.radioConfig = radioConfig
with caplog.at_level(logging.DEBUG):
anode.writeConfig()
assert re.search(r&#39;Wrote config&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_requestChannel_not_localNode(caplog):
&#34;&#34;&#34;Test _requestChannel()&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode._requestChannel(0)
assert re.search(r&#39;Requesting channel 0 info from remote node&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_requestChannel_localNode(caplog):
&#34;&#34;&#34;Test _requestChannel()&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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&#39;Requesting channel 0&#39;, caplog.text, re.MULTILINE)
assert not re.search(r&#39;from remote node&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_onResponseRequestChannel(caplog):
&#34;&#34;&#34;Test onResponseRequestChannel()&#34;&#34;&#34;
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
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 = {
&#39;from&#39;: 2475227164,
&#39;to&#39;: 2475227164,
&#39;decoded&#39;: {
&#39;portnum&#39;: &#39;ADMIN_APP&#39;,
&#39;payload&#39;: b&#39;:\t\x12\x05\x18\x03&#34;\x01\x01\x18\x01&#39;,
&#39;requestId&#39;: 2615094405,
&#39;admin&#39;: {
&#39;getChannelResponse&#39;: {
&#39;settings&#39;: {
&#39;modemConfig&#39;: &#39;Bw125Cr48Sf4096&#39;,
&#39;psk&#39;: &#39;AQ==&#39;
},
&#39;role&#39;: &#39;PRIMARY&#39;
},
&#39;raw&#39;: msg1,
}
},
&#39;id&#39;: 1692918436,
&#39;hopLimit&#39;: 3,
&#39;priority&#39;:
&#39;RELIABLE&#39;,
&#39;raw&#39;: &#39;fake&#39;,
&#39;fromId&#39;: &#39;!9388f81c&#39;,
&#39;toId&#39;: &#39;!9388f81c&#39;
}
# no other channels
packet2 = {
&#39;from&#39;: 2475227164,
&#39;to&#39;: 2475227164,
&#39;decoded&#39;: {
&#39;portnum&#39;: &#39;ADMIN_APP&#39;,
&#39;payload&#39;: b&#39;:\x04\x08\x02\x12\x00&#39;,
&#39;requestId&#39;: 743049663,
&#39;admin&#39;: {
&#39;getChannelResponse&#39;: {
&#39;index&#39;: 2,
&#39;settings&#39;: {}
},
&#39;raw&#39;: msg2,
}
},
&#39;id&#39;: 1692918456,
&#39;rxTime&#39;: 1640202239,
&#39;hopLimit&#39;: 3,
&#39;priority&#39;: &#39;RELIABLE&#39;,
&#39;raw&#39;: &#39;faked&#39;,
&#39;fromId&#39;: &#39;!9388f81c&#39;,
&#39;toId&#39;: &#39;!9388f81c&#39;
}
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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&#39;Received channel&#39;, caplog.text, re.MULTILINE)
anode.onResponseRequestChannel(packet2)
assert re.search(r&#39;Received channel&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;Finished downloading channels&#39;, caplog.text, re.MULTILINE)
assert len(anode.channels) == 8
assert anode.channels[0].settings.modem_config == 3
assert anode.channels[1].settings.name == &#39;&#39;
assert anode.channels[2].settings.name == &#39;&#39;
assert anode.channels[3].settings.name == &#39;&#39;
assert anode.channels[4].settings.name == &#39;&#39;
assert anode.channels[5].settings.name == &#39;&#39;
assert anode.channels[6].settings.name == &#39;&#39;
assert anode.channels[7].settings.name == &#39;&#39;
@pytest.mark.unit
def test_onResponseRequestSetting(caplog):
&#34;&#34;&#34;Test onResponseRequestSetting()&#34;&#34;&#34;
# Note: Split out the get_radio_response to a MagicMock
# so it could be &#34;returned&#34; (not really sure how to do that
# in a python dict.
amsg = MagicMock(autospec=AdminMessage)
amsg.get_radio_response = &#34;&#34;&#34;{
preferences {
phone_timeout_secs: 900
ls_secs: 300
position_broadcast_smart: true
position_flags: 35
}
}&#34;&#34;&#34;
packet = {
&#39;from&#39;: 2475227164,
&#39;to&#39;: 2475227164,
&#39;decoded&#39;: {
&#39;portnum&#39;: &#39;ADMIN_APP&#39;,
&#39;payload&#39;: b&#39;*\x0e\n\x0c0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#&#39;,
&#39;requestId&#39;: 3145147848,
&#39;admin&#39;: {
&#39;getRadioResponse&#39;: {
&#39;preferences&#39;: {
&#39;phoneTimeoutSecs&#39;: 900,
&#39;lsSecs&#39;: 300,
&#39;positionBroadcastSmart&#39;: True,
&#39;positionFlags&#39;: 35
}
},
&#39;raw&#39;: amsg
},
&#39;id&#39;: 365963704,
&#39;rxTime&#39;: 1640195197,
&#39;hopLimit&#39;: 3,
&#39;priority&#39;: &#39;RELIABLE&#39;,
&#39;raw&#39;: &#39;faked&#39;,
&#39;fromId&#39;: &#39;!9388f81c&#39;,
&#39;toId&#39;: &#39;!9388f81c&#39;
}
}
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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&#39;Received radio config, now fetching channels..&#39;, caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_onResponseRequestSetting_with_error(capsys):
&#34;&#34;&#34;Test onResponseRequestSetting() with an error&#34;&#34;&#34;
packet = {
&#39;from&#39;: 2475227164,
&#39;to&#39;: 2475227164,
&#39;decoded&#39;: {
&#39;portnum&#39;: &#39;ADMIN_APP&#39;,
&#39;payload&#39;: b&#39;*\x0e\n\x0c0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#&#39;,
&#39;requestId&#39;: 3145147848,
&#39;routing&#39;: {
&#39;errorReason&#39;: &#39;some made up error&#39;,
},
&#39;admin&#39;: {
&#39;getRadioResponse&#39;: {
&#39;preferences&#39;: {
&#39;phoneTimeoutSecs&#39;: 900,
&#39;lsSecs&#39;: 300,
&#39;positionBroadcastSmart&#39;: True,
&#39;positionFlags&#39;: 35
}
},
},
&#39;id&#39;: 365963704,
&#39;rxTime&#39;: 1640195197,
&#39;hopLimit&#39;: 3,
&#39;priority&#39;: &#39;RELIABLE&#39;,
&#39;fromId&#39;: &#39;!9388f81c&#39;,
&#39;toId&#39;: &#39;!9388f81c&#39;
}
}
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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&#39;Error on response&#39;, out)
assert err == &#39;&#39;</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="meshtastic.tests.test_node.test_deleteChannel_secondary"><code class="name flex">
<span>def <span class="ident">test_deleteChannel_secondary</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Try to delete a secondary channel.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_deleteChannel_secondary():
&#34;&#34;&#34;Try to delete a secondary channel.&#34;&#34;&#34;
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;testing&#39;
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(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, noProto=True)
anode.channels = channels
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;testing&#39;
assert channels[2].settings.name == &#39;&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;
anode.deleteChannel(1)
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;&#39;
assert channels[2].settings.name == &#39;&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_deleteChannel_secondary_with_admin_channel_after_testing"><code class="name flex">
<span>def <span class="ident">test_deleteChannel_secondary_with_admin_channel_after_testing</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Try to delete a secondary channel where there is an admin channel.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_deleteChannel_secondary_with_admin_channel_after_testing():
&#34;&#34;&#34;Try to delete a secondary channel where there is an admin channel.&#34;&#34;&#34;
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;testing&#39;
channel3 = Channel(index=3, role=2)
channel3.settings.name = &#39;admin&#39;
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(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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 == &#39;testing&#39;
assert channels[2].settings.name == &#39;admin&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;
anode.deleteChannel(1)
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;admin&#39;
assert channels[2].settings.name == &#39;&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_deleteChannel_secondary_with_admin_channel_before_testing"><code class="name flex">
<span>def <span class="ident">test_deleteChannel_secondary_with_admin_channel_before_testing</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Try to delete a secondary channel where there is an admin channel.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_deleteChannel_secondary_with_admin_channel_before_testing():
&#34;&#34;&#34;Try to delete a secondary channel where there is an admin channel.&#34;&#34;&#34;
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;admin&#39;
channel3 = Channel(index=3, role=2)
channel3.settings.name = &#39;testing&#39;
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(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, noProto=True)
anode.channels = channels
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;admin&#39;
assert channels[2].settings.name == &#39;testing&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;
anode.deleteChannel(2)
assert len(anode.channels) == 8
assert channels[0].settings.modem_config == 3
assert channels[1].settings.name == &#39;admin&#39;
assert channels[2].settings.name == &#39;&#39;
assert channels[3].settings.name == &#39;&#39;
assert channels[4].settings.name == &#39;&#39;
assert channels[5].settings.name == &#39;&#39;
assert channels[6].settings.name == &#39;&#39;
assert channels[7].settings.name == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_deleteChannel_try_to_delete_primary_channel"><code class="name flex">
<span>def <span class="ident">test_deleteChannel_try_to_delete_primary_channel</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Try to delete primary channel.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_deleteChannel_try_to_delete_primary_channel(capsys):
&#34;&#34;&#34;Try to delete primary channel.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
# 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&#39;Warning: Only SECONDARY channels can be deleted&#39;, out, re.MULTILINE)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_exitSimulator"><code class="name flex">
<span>def <span class="ident">test_exitSimulator</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test exitSimulator</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_exitSimulator(caplog):
&#34;&#34;&#34;Test exitSimulator&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.exitSimulator()
assert re.search(r&#39;in exitSimulator&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_getAdminChannelIndex"><code class="name flex">
<span>def <span class="ident">test_getAdminChannelIndex</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Get the 'admin' channel index.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_getAdminChannelIndex(capsys):
&#34;&#34;&#34;Get the &#39;admin&#39; channel index.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;admin&#39;
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</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_getAdminChannelIndex_when_no_admin_named_channel"><code class="name flex">
<span>def <span class="ident">test_getAdminChannelIndex_when_no_admin_named_channel</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Get the 'admin' channel when there is not one.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_getAdminChannelIndex_when_no_admin_named_channel(capsys):
&#34;&#34;&#34;Get the &#39;admin&#39; channel when there is not one.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
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</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_getChannelByChannelIndex"><code class="name flex">
<span>def <span class="ident">test_getChannelByChannelIndex</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test getChannelByChannelIndex()</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_getChannelByChannelIndex():
&#34;&#34;&#34;Test getChannelByChannelIndex()&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
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</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_getChannelByName"><code class="name flex">
<span>def <span class="ident">test_getChannelByName</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Get a channel by the name.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_getChannelByName(capsys):
&#34;&#34;&#34;Get a channel by the name.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;admin&#39;
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(&#39;admin&#39;)
assert ch.index == 2</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_getChannelByName_invalid_name"><code class="name flex">
<span>def <span class="ident">test_getChannelByName_invalid_name</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Get a channel by the name but one that is not present.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_getChannelByName_invalid_name(capsys):
&#34;&#34;&#34;Get a channel by the name but one that is not present.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;admin&#39;
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(&#39;testing&#39;)
assert ch is None</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_getDisabledChannel"><code class="name flex">
<span>def <span class="ident">test_getDisabledChannel</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Get the first disabled channel.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_getDisabledChannel(capsys):
&#34;&#34;&#34;Get the first disabled channel.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;testingA&#39;
channel3 = Channel(index=3, role=2)
channel3.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel3.settings.name = &#39;testingB&#39;
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</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_getDisabledChannel_where_all_channels_are_used"><code class="name flex">
<span>def <span class="ident">test_getDisabledChannel_where_all_channels_are_used</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Get the first disabled channel.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_getDisabledChannel_where_all_channels_are_used(capsys):
&#34;&#34;&#34;Get the first disabled channel.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
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</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_node"><code class="name flex">
<span>def <span class="ident">test_node</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test that we can instantiate a Node</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_node(capsys):
&#34;&#34;&#34;Test that we can instantiate a Node&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
radioConfig = RadioConfig()
anode.radioConfig = radioConfig
anode.showChannels()
anode.showInfo()
out, err = capsys.readouterr()
assert re.search(r&#39;Preferences&#39;, out)
assert re.search(r&#39;Channels&#39;, out)
assert re.search(r&#39;Primary channel URL&#39;, out)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_node_reqquestConfig"><code class="name flex">
<span>def <span class="ident">test_node_reqquestConfig</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test run requestConfig</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_node_reqquestConfig():
&#34;&#34;&#34;Test run requestConfig&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
amesg = MagicMock(autospec=AdminMessage)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
with patch(&#39;meshtastic.admin_pb2.AdminMessage&#39;, return_value=amesg):
anode = Node(mo, &#39;bar&#39;)
anode.requestConfig()</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_onResponseRequestChannel"><code class="name flex">
<span>def <span class="ident">test_onResponseRequestChannel</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test onResponseRequestChannel()</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_onResponseRequestChannel(caplog):
&#34;&#34;&#34;Test onResponseRequestChannel()&#34;&#34;&#34;
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
channel1.settings.psk = b&#39;\x01&#39;
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 = {
&#39;from&#39;: 2475227164,
&#39;to&#39;: 2475227164,
&#39;decoded&#39;: {
&#39;portnum&#39;: &#39;ADMIN_APP&#39;,
&#39;payload&#39;: b&#39;:\t\x12\x05\x18\x03&#34;\x01\x01\x18\x01&#39;,
&#39;requestId&#39;: 2615094405,
&#39;admin&#39;: {
&#39;getChannelResponse&#39;: {
&#39;settings&#39;: {
&#39;modemConfig&#39;: &#39;Bw125Cr48Sf4096&#39;,
&#39;psk&#39;: &#39;AQ==&#39;
},
&#39;role&#39;: &#39;PRIMARY&#39;
},
&#39;raw&#39;: msg1,
}
},
&#39;id&#39;: 1692918436,
&#39;hopLimit&#39;: 3,
&#39;priority&#39;:
&#39;RELIABLE&#39;,
&#39;raw&#39;: &#39;fake&#39;,
&#39;fromId&#39;: &#39;!9388f81c&#39;,
&#39;toId&#39;: &#39;!9388f81c&#39;
}
# no other channels
packet2 = {
&#39;from&#39;: 2475227164,
&#39;to&#39;: 2475227164,
&#39;decoded&#39;: {
&#39;portnum&#39;: &#39;ADMIN_APP&#39;,
&#39;payload&#39;: b&#39;:\x04\x08\x02\x12\x00&#39;,
&#39;requestId&#39;: 743049663,
&#39;admin&#39;: {
&#39;getChannelResponse&#39;: {
&#39;index&#39;: 2,
&#39;settings&#39;: {}
},
&#39;raw&#39;: msg2,
}
},
&#39;id&#39;: 1692918456,
&#39;rxTime&#39;: 1640202239,
&#39;hopLimit&#39;: 3,
&#39;priority&#39;: &#39;RELIABLE&#39;,
&#39;raw&#39;: &#39;faked&#39;,
&#39;fromId&#39;: &#39;!9388f81c&#39;,
&#39;toId&#39;: &#39;!9388f81c&#39;
}
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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&#39;Received channel&#39;, caplog.text, re.MULTILINE)
anode.onResponseRequestChannel(packet2)
assert re.search(r&#39;Received channel&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;Finished downloading channels&#39;, caplog.text, re.MULTILINE)
assert len(anode.channels) == 8
assert anode.channels[0].settings.modem_config == 3
assert anode.channels[1].settings.name == &#39;&#39;
assert anode.channels[2].settings.name == &#39;&#39;
assert anode.channels[3].settings.name == &#39;&#39;
assert anode.channels[4].settings.name == &#39;&#39;
assert anode.channels[5].settings.name == &#39;&#39;
assert anode.channels[6].settings.name == &#39;&#39;
assert anode.channels[7].settings.name == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_onResponseRequestSetting"><code class="name flex">
<span>def <span class="ident">test_onResponseRequestSetting</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test onResponseRequestSetting()</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_onResponseRequestSetting(caplog):
&#34;&#34;&#34;Test onResponseRequestSetting()&#34;&#34;&#34;
# Note: Split out the get_radio_response to a MagicMock
# so it could be &#34;returned&#34; (not really sure how to do that
# in a python dict.
amsg = MagicMock(autospec=AdminMessage)
amsg.get_radio_response = &#34;&#34;&#34;{
preferences {
phone_timeout_secs: 900
ls_secs: 300
position_broadcast_smart: true
position_flags: 35
}
}&#34;&#34;&#34;
packet = {
&#39;from&#39;: 2475227164,
&#39;to&#39;: 2475227164,
&#39;decoded&#39;: {
&#39;portnum&#39;: &#39;ADMIN_APP&#39;,
&#39;payload&#39;: b&#39;*\x0e\n\x0c0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#&#39;,
&#39;requestId&#39;: 3145147848,
&#39;admin&#39;: {
&#39;getRadioResponse&#39;: {
&#39;preferences&#39;: {
&#39;phoneTimeoutSecs&#39;: 900,
&#39;lsSecs&#39;: 300,
&#39;positionBroadcastSmart&#39;: True,
&#39;positionFlags&#39;: 35
}
},
&#39;raw&#39;: amsg
},
&#39;id&#39;: 365963704,
&#39;rxTime&#39;: 1640195197,
&#39;hopLimit&#39;: 3,
&#39;priority&#39;: &#39;RELIABLE&#39;,
&#39;raw&#39;: &#39;faked&#39;,
&#39;fromId&#39;: &#39;!9388f81c&#39;,
&#39;toId&#39;: &#39;!9388f81c&#39;
}
}
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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&#39;Received radio config, now fetching channels..&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_onResponseRequestSetting_with_error"><code class="name flex">
<span>def <span class="ident">test_onResponseRequestSetting_with_error</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test onResponseRequestSetting() with an error</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_onResponseRequestSetting_with_error(capsys):
&#34;&#34;&#34;Test onResponseRequestSetting() with an error&#34;&#34;&#34;
packet = {
&#39;from&#39;: 2475227164,
&#39;to&#39;: 2475227164,
&#39;decoded&#39;: {
&#39;portnum&#39;: &#39;ADMIN_APP&#39;,
&#39;payload&#39;: b&#39;*\x0e\n\x0c0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#&#39;,
&#39;requestId&#39;: 3145147848,
&#39;routing&#39;: {
&#39;errorReason&#39;: &#39;some made up error&#39;,
},
&#39;admin&#39;: {
&#39;getRadioResponse&#39;: {
&#39;preferences&#39;: {
&#39;phoneTimeoutSecs&#39;: 900,
&#39;lsSecs&#39;: 300,
&#39;positionBroadcastSmart&#39;: True,
&#39;positionFlags&#39;: 35
}
},
},
&#39;id&#39;: 365963704,
&#39;rxTime&#39;: 1640195197,
&#39;hopLimit&#39;: 3,
&#39;priority&#39;: &#39;RELIABLE&#39;,
&#39;fromId&#39;: &#39;!9388f81c&#39;,
&#39;toId&#39;: &#39;!9388f81c&#39;
}
}
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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&#39;Error on response&#39;, out)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_reboot"><code class="name flex">
<span>def <span class="ident">test_reboot</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test reboot</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_reboot(caplog):
&#34;&#34;&#34;Test reboot&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.reboot()
assert re.search(r&#39;Telling node to reboot&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_requestChannel_localNode"><code class="name flex">
<span>def <span class="ident">test_requestChannel_localNode</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test _requestChannel()</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_requestChannel_localNode(caplog):
&#34;&#34;&#34;Test _requestChannel()&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, 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&#39;Requesting channel 0&#39;, caplog.text, re.MULTILINE)
assert not re.search(r&#39;from remote node&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_requestChannel_not_localNode"><code class="name flex">
<span>def <span class="ident">test_requestChannel_not_localNode</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test _requestChannel()</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_requestChannel_not_localNode(caplog):
&#34;&#34;&#34;Test _requestChannel()&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
with patch(&#39;meshtastic.serial_interface.SerialInterface&#39;, return_value=iface) as mo:
mo.localNode.getChannelByName.return_value = None
mo.myInfo.max_channels = 8
anode = Node(mo, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode._requestChannel(0)
assert re.search(r&#39;Requesting channel 0 info from remote node&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_setOwner_and_team"><code class="name flex">
<span>def <span class="ident">test_setOwner_and_team</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test setOwner</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_setOwner_and_team(caplog):
&#34;&#34;&#34;Test setOwner&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name =&#39;Test123&#39;, short_name=&#39;123&#39;, team=1)
assert re.search(r&#39;p.set_owner.long_name:Test123:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.short_name:123:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.is_licensed:False&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.team:1&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_setOwner_no_short_name"><code class="name flex">
<span>def <span class="ident">test_setOwner_no_short_name</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test setOwner</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_setOwner_no_short_name(caplog):
&#34;&#34;&#34;Test setOwner&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name =&#39;Test123&#39;)
assert re.search(r&#39;p.set_owner.long_name:Test123:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.short_name:Tst:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.is_licensed:False&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.team:0&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_setOwner_no_short_name_and_long_name_has_words"><code class="name flex">
<span>def <span class="ident">test_setOwner_no_short_name_and_long_name_has_words</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test setOwner</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_setOwner_no_short_name_and_long_name_has_words(caplog):
&#34;&#34;&#34;Test setOwner&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name =&#39;A B C&#39;, is_licensed=True)
assert re.search(r&#39;p.set_owner.long_name:A B C:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.short_name:ABC:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.is_licensed:True&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.team:0&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_setOwner_no_short_name_and_long_name_is_short"><code class="name flex">
<span>def <span class="ident">test_setOwner_no_short_name_and_long_name_is_short</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test setOwner</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_setOwner_no_short_name_and_long_name_is_short(caplog):
&#34;&#34;&#34;Test setOwner&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name =&#39;Tnt&#39;)
assert re.search(r&#39;p.set_owner.long_name:Tnt:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.short_name:Tnt:&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.is_licensed:False&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;p.set_owner.team:0&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_setURL_empty_url"><code class="name flex">
<span>def <span class="ident">test_setURL_empty_url</span></span>(<span>)</span>
</code></dt>
<dd>
<div class="desc"><p>Test reboot</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_setURL_empty_url():
&#34;&#34;&#34;Test reboot&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
with pytest.raises(SystemExit) as pytest_wrapped_e:
anode.setURL(&#39;&#39;)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_setURL_valid_URL"><code class="name flex">
<span>def <span class="ident">test_setURL_valid_URL</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test setURL</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_setURL_valid_URL(caplog):
&#34;&#34;&#34;Test setURL&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
url = &#34;https://www.meshtastic.org/d/#CgUYAyIBAQ&#34;
with caplog.at_level(logging.DEBUG):
anode = Node(iface, &#39;bar&#39;, noProto=True)
anode.radioConfig = &#39;baz&#39;
channels = [&#39;zoo&#39;]
anode.channels = channels
anode.setURL(url)
assert re.search(r&#39;Channel i:0&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;modem_config: Bw125Cr48Sf4096&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;psk: &#34;\\001&#34;&#39;, caplog.text, re.MULTILINE)
assert re.search(r&#39;role: PRIMARY&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_setURL_valid_URL_but_no_settings"><code class="name flex">
<span>def <span class="ident">test_setURL_valid_URL_but_no_settings</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test setURL</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_setURL_valid_URL_but_no_settings(caplog):
&#34;&#34;&#34;Test setURL&#34;&#34;&#34;
iface = MagicMock(autospec=SerialInterface)
url = &#34;https://www.meshtastic.org/d/#&#34;
with pytest.raises(SystemExit) as pytest_wrapped_e:
anode = Node(iface, &#39;bar&#39;, noProto=True)
anode.radioConfig = &#39;baz&#39;
anode.setURL(url)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 1</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_showChannels"><code class="name flex">
<span>def <span class="ident">test_showChannels</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test showChannels</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_showChannels(capsys):
&#34;&#34;&#34;Test showChannels&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;)
# 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&#39;\x01&#39;
channel2 = Channel(index=2, role=2)
channel2.settings.psk = b&#39;\x8a\x94y\x0e\xc6\xc9\x1e5\x91\x12@\xa60\xa8\xb43\x87\x00\xf2K\x0e\xe7\x7fAz\xcd\xf5\xb0\x900\xa84&#39;
channel2.settings.name = &#39;testing&#39;
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&#39;Channels:&#39;, out, re.MULTILINE)
# primary channel
assert re.search(r&#39;Primary channel URL&#39;, out, re.MULTILINE)
assert re.search(r&#39;PRIMARY psk=default &#39;, out, re.MULTILINE)
assert re.search(r&#39;&#34;modemConfig&#34;: &#34;Bw125Cr48Sf4096&#34;&#39;, out, re.MULTILINE)
assert re.search(r&#39;&#34;psk&#34;: &#34;AQ==&#34;&#39;, out, re.MULTILINE)
# secondary channel
assert re.search(r&#39;SECONDARY psk=secret &#39;, out, re.MULTILINE)
assert re.search(r&#39;&#34;psk&#34;: &#34;ipR5DsbJHjWREkCmMKi0M4cA8ksO539Bes31sJAwqDQ=&#34;&#39;, out, re.MULTILINE)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_turnOffEncryptionOnPrimaryChannel"><code class="name flex">
<span>def <span class="ident">test_turnOffEncryptionOnPrimaryChannel</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Turn off encryption when there is a psk.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_turnOffEncryptionOnPrimaryChannel(capsys):
&#34;&#34;&#34;Turn off encryption when there is a psk.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
channel1 = Channel(index=1, role=1)
channel1.settings.modem_config = 3
# value from using &#34;--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b &#34;
channel1.settings.psk = b&#39;\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++\x1a\x1a\x1a\x1a++++&#39;
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&#39;Writing modified channels to device&#39;, out)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_writeConfig"><code class="name flex">
<span>def <span class="ident">test_writeConfig</span></span>(<span>caplog)</span>
</code></dt>
<dd>
<div class="desc"><p>Test writeConfig</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_writeConfig(caplog):
&#34;&#34;&#34;Test writeConfig&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, noProto=True)
radioConfig = RadioConfig()
anode.radioConfig = radioConfig
with caplog.at_level(logging.DEBUG):
anode.writeConfig()
assert re.search(r&#39;Wrote config&#39;, caplog.text, re.MULTILINE)</code></pre>
</details>
</dd>
<dt id="meshtastic.tests.test_node.test_writeConfig_with_no_radioConfig"><code class="name flex">
<span>def <span class="ident">test_writeConfig_with_no_radioConfig</span></span>(<span>capsys)</span>
</code></dt>
<dd>
<div class="desc"><p>Test writeConfig with no radioConfig.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@pytest.mark.unit
def test_writeConfig_with_no_radioConfig(capsys):
&#34;&#34;&#34;Test writeConfig with no radioConfig.&#34;&#34;&#34;
anode = Node(&#39;foo&#39;, &#39;bar&#39;, 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&#39;Error: No RadioConfig has been read&#39;, out)
assert err == &#39;&#39;</code></pre>
</details>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="meshtastic.tests.test_node.AdminMessage"><code class="flex name class">
<span>class <span class="ident">AdminMessage</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google.protobuf.pyext._message.CMessage</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="meshtastic.tests.test_node.AdminMessage.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.tests.test_node.AdminMessage.confirm_set_channel"><code class="name">var <span class="ident">confirm_set_channel</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.confirm_set_channel</p></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.confirm_set_radio"><code class="name">var <span class="ident">confirm_set_radio</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.confirm_set_radio</p></div>
</dd>
<dt id="meshtastic.tests.test_node.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.tests.test_node.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>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.get_channel_response"><code class="name">var <span class="ident">get_channel_response</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.get_channel_response</p></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.get_radio_request"><code class="name">var <span class="ident">get_radio_request</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.get_radio_request</p></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.get_radio_response"><code class="name">var <span class="ident">get_radio_response</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.get_radio_response</p></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.reboot_seconds"><code class="name">var <span class="ident">reboot_seconds</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.reboot_seconds</p></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.set_channel"><code class="name">var <span class="ident">set_channel</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.set_channel</p></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.set_owner"><code class="name">var <span class="ident">set_owner</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.set_owner</p></div>
</dd>
<dt id="meshtastic.tests.test_node.AdminMessage.set_radio"><code class="name">var <span class="ident">set_radio</span></code></dt>
<dd>
<div class="desc"><p>Field AdminMessage.set_radio</p></div>
</dd>
</dl>
</dd>
<dt id="meshtastic.tests.test_node.Channel"><code class="flex name class">
<span>class <span class="ident">Channel</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google.protobuf.pyext._message.CMessage</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="meshtastic.tests.test_node.Channel.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.Channel.DISABLED"><code class="name">var <span class="ident">DISABLED</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.Channel.PRIMARY"><code class="name">var <span class="ident">PRIMARY</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.Channel.Role"><code class="name">var <span class="ident">Role</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.Channel.SECONDARY"><code class="name">var <span class="ident">SECONDARY</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.tests.test_node.Channel.index"><code class="name">var <span class="ident">index</span></code></dt>
<dd>
<div class="desc"><p>Field Channel.index</p></div>
</dd>
<dt id="meshtastic.tests.test_node.Channel.role"><code class="name">var <span class="ident">role</span></code></dt>
<dd>
<div class="desc"><p>Field Channel.role</p></div>
</dd>
<dt id="meshtastic.tests.test_node.Channel.settings"><code class="name">var <span class="ident">settings</span></code></dt>
<dd>
<div class="desc"><p>Field Channel.settings</p></div>
</dd>
</dl>
</dd>
<dt id="meshtastic.tests.test_node.RadioConfig"><code class="flex name class">
<span>class <span class="ident">RadioConfig</span></span>
<span>(</span><span>*args, **kwargs)</span>
</code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li>google.protobuf.pyext._message.CMessage</li>
<li>google.protobuf.message.Message</li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="meshtastic.tests.test_node.RadioConfig.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="meshtastic.tests.test_node.RadioConfig.UserPreferences"><code class="name">var <span class="ident">UserPreferences</span></code></dt>
<dd>
<div class="desc"><p>A ProtocolMessage</p></div>
</dd>
</dl>
<h3>Instance variables</h3>
<dl>
<dt id="meshtastic.tests.test_node.RadioConfig.preferences"><code class="name">var <span class="ident">preferences</span></code></dt>
<dd>
<div class="desc"><p>Field RadioConfig.preferences</p></div>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
</ul>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="meshtastic.tests.test_node.test_deleteChannel_secondary" href="#meshtastic.tests.test_node.test_deleteChannel_secondary">test_deleteChannel_secondary</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_deleteChannel_secondary_with_admin_channel_after_testing" href="#meshtastic.tests.test_node.test_deleteChannel_secondary_with_admin_channel_after_testing">test_deleteChannel_secondary_with_admin_channel_after_testing</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_deleteChannel_secondary_with_admin_channel_before_testing" href="#meshtastic.tests.test_node.test_deleteChannel_secondary_with_admin_channel_before_testing">test_deleteChannel_secondary_with_admin_channel_before_testing</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_deleteChannel_try_to_delete_primary_channel" href="#meshtastic.tests.test_node.test_deleteChannel_try_to_delete_primary_channel">test_deleteChannel_try_to_delete_primary_channel</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_exitSimulator" href="#meshtastic.tests.test_node.test_exitSimulator">test_exitSimulator</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_getAdminChannelIndex" href="#meshtastic.tests.test_node.test_getAdminChannelIndex">test_getAdminChannelIndex</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_getAdminChannelIndex_when_no_admin_named_channel" href="#meshtastic.tests.test_node.test_getAdminChannelIndex_when_no_admin_named_channel">test_getAdminChannelIndex_when_no_admin_named_channel</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_getChannelByChannelIndex" href="#meshtastic.tests.test_node.test_getChannelByChannelIndex">test_getChannelByChannelIndex</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_getChannelByName" href="#meshtastic.tests.test_node.test_getChannelByName">test_getChannelByName</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_getChannelByName_invalid_name" href="#meshtastic.tests.test_node.test_getChannelByName_invalid_name">test_getChannelByName_invalid_name</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_getDisabledChannel" href="#meshtastic.tests.test_node.test_getDisabledChannel">test_getDisabledChannel</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_getDisabledChannel_where_all_channels_are_used" href="#meshtastic.tests.test_node.test_getDisabledChannel_where_all_channels_are_used">test_getDisabledChannel_where_all_channels_are_used</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_node" href="#meshtastic.tests.test_node.test_node">test_node</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_node_reqquestConfig" href="#meshtastic.tests.test_node.test_node_reqquestConfig">test_node_reqquestConfig</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_onResponseRequestChannel" href="#meshtastic.tests.test_node.test_onResponseRequestChannel">test_onResponseRequestChannel</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_onResponseRequestSetting" href="#meshtastic.tests.test_node.test_onResponseRequestSetting">test_onResponseRequestSetting</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_onResponseRequestSetting_with_error" href="#meshtastic.tests.test_node.test_onResponseRequestSetting_with_error">test_onResponseRequestSetting_with_error</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_reboot" href="#meshtastic.tests.test_node.test_reboot">test_reboot</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_requestChannel_localNode" href="#meshtastic.tests.test_node.test_requestChannel_localNode">test_requestChannel_localNode</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_requestChannel_not_localNode" href="#meshtastic.tests.test_node.test_requestChannel_not_localNode">test_requestChannel_not_localNode</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_setOwner_and_team" href="#meshtastic.tests.test_node.test_setOwner_and_team">test_setOwner_and_team</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_setOwner_no_short_name" href="#meshtastic.tests.test_node.test_setOwner_no_short_name">test_setOwner_no_short_name</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_setOwner_no_short_name_and_long_name_has_words" href="#meshtastic.tests.test_node.test_setOwner_no_short_name_and_long_name_has_words">test_setOwner_no_short_name_and_long_name_has_words</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_setOwner_no_short_name_and_long_name_is_short" href="#meshtastic.tests.test_node.test_setOwner_no_short_name_and_long_name_is_short">test_setOwner_no_short_name_and_long_name_is_short</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_setURL_empty_url" href="#meshtastic.tests.test_node.test_setURL_empty_url">test_setURL_empty_url</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_setURL_valid_URL" href="#meshtastic.tests.test_node.test_setURL_valid_URL">test_setURL_valid_URL</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_setURL_valid_URL_but_no_settings" href="#meshtastic.tests.test_node.test_setURL_valid_URL_but_no_settings">test_setURL_valid_URL_but_no_settings</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_showChannels" href="#meshtastic.tests.test_node.test_showChannels">test_showChannels</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_turnOffEncryptionOnPrimaryChannel" href="#meshtastic.tests.test_node.test_turnOffEncryptionOnPrimaryChannel">test_turnOffEncryptionOnPrimaryChannel</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_writeConfig" href="#meshtastic.tests.test_node.test_writeConfig">test_writeConfig</a></code></li>
<li><code><a title="meshtastic.tests.test_node.test_writeConfig_with_no_radioConfig" href="#meshtastic.tests.test_node.test_writeConfig_with_no_radioConfig">test_writeConfig_with_no_radioConfig</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="meshtastic.tests.test_node.AdminMessage" href="#meshtastic.tests.test_node.AdminMessage">AdminMessage</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.tests.test_node.AdminMessage.DESCRIPTOR" href="#meshtastic.tests.test_node.AdminMessage.DESCRIPTOR">DESCRIPTOR</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.confirm_set_channel" href="#meshtastic.tests.test_node.AdminMessage.confirm_set_channel">confirm_set_channel</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.confirm_set_radio" href="#meshtastic.tests.test_node.AdminMessage.confirm_set_radio">confirm_set_radio</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.exit_simulator" href="#meshtastic.tests.test_node.AdminMessage.exit_simulator">exit_simulator</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.get_channel_request" href="#meshtastic.tests.test_node.AdminMessage.get_channel_request">get_channel_request</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.get_channel_response" href="#meshtastic.tests.test_node.AdminMessage.get_channel_response">get_channel_response</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.get_radio_request" href="#meshtastic.tests.test_node.AdminMessage.get_radio_request">get_radio_request</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.get_radio_response" href="#meshtastic.tests.test_node.AdminMessage.get_radio_response">get_radio_response</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.reboot_seconds" href="#meshtastic.tests.test_node.AdminMessage.reboot_seconds">reboot_seconds</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.set_channel" href="#meshtastic.tests.test_node.AdminMessage.set_channel">set_channel</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.set_owner" href="#meshtastic.tests.test_node.AdminMessage.set_owner">set_owner</a></code></li>
<li><code><a title="meshtastic.tests.test_node.AdminMessage.set_radio" href="#meshtastic.tests.test_node.AdminMessage.set_radio">set_radio</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="meshtastic.tests.test_node.Channel" href="#meshtastic.tests.test_node.Channel">Channel</a></code></h4>
<ul class="two-column">
<li><code><a title="meshtastic.tests.test_node.Channel.DESCRIPTOR" href="#meshtastic.tests.test_node.Channel.DESCRIPTOR">DESCRIPTOR</a></code></li>
<li><code><a title="meshtastic.tests.test_node.Channel.DISABLED" href="#meshtastic.tests.test_node.Channel.DISABLED">DISABLED</a></code></li>
<li><code><a title="meshtastic.tests.test_node.Channel.PRIMARY" href="#meshtastic.tests.test_node.Channel.PRIMARY">PRIMARY</a></code></li>
<li><code><a title="meshtastic.tests.test_node.Channel.Role" href="#meshtastic.tests.test_node.Channel.Role">Role</a></code></li>
<li><code><a title="meshtastic.tests.test_node.Channel.SECONDARY" href="#meshtastic.tests.test_node.Channel.SECONDARY">SECONDARY</a></code></li>
<li><code><a title="meshtastic.tests.test_node.Channel.index" href="#meshtastic.tests.test_node.Channel.index">index</a></code></li>
<li><code><a title="meshtastic.tests.test_node.Channel.role" href="#meshtastic.tests.test_node.Channel.role">role</a></code></li>
<li><code><a title="meshtastic.tests.test_node.Channel.settings" href="#meshtastic.tests.test_node.Channel.settings">settings</a></code></li>
</ul>
</li>
<li>
<h4><code><a title="meshtastic.tests.test_node.RadioConfig" href="#meshtastic.tests.test_node.RadioConfig">RadioConfig</a></code></h4>
<ul class="">
<li><code><a title="meshtastic.tests.test_node.RadioConfig.DESCRIPTOR" href="#meshtastic.tests.test_node.RadioConfig.DESCRIPTOR">DESCRIPTOR</a></code></li>
<li><code><a title="meshtastic.tests.test_node.RadioConfig.UserPreferences" href="#meshtastic.tests.test_node.RadioConfig.UserPreferences">UserPreferences</a></code></li>
<li><code><a title="meshtastic.tests.test_node.RadioConfig.preferences" href="#meshtastic.tests.test_node.RadioConfig.preferences">preferences</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.1.dev1+g4aa70de.d20211229</a>.</p>
</footer>
</body>
</html>