Compare commits

..

59 Commits

Author SHA1 Message Date
mkinney
069056edad Update setup.py 2022-01-27 17:12:50 -08:00
github-actions
19bd510975 Update protobuf submodule 2022-01-28 01:12:41 +00:00
mkinney
7979efc0a1 Merge pull request #247 from mkinney/remote_hardware
remote hardware tests
2022-01-27 17:11:37 -08:00
Mike Kinney
66866a4c65 fix logic 2022-01-27 17:09:13 -08:00
Mike Kinney
e6fb066fe5 get last couple of lines covered in remote_hardware 2022-01-27 17:05:16 -08:00
Mike Kinney
5841979566 remove line 2022-01-27 17:00:53 -08:00
Mike Kinney
529f50edc6 remote hardware tests 2022-01-27 16:54:47 -08:00
github-actions
5895e8fb4d Update protobuf submodule 2022-01-27 14:21:10 +00:00
mkinney
49dcf71116 Update setup.py 2022-01-26 20:32:45 -08:00
Jm Casler
5778552380 updating proto submodule to latest 2022-01-26 13:35:48 -08:00
Jm Casler
592ecc9997 updating proto submodule to latest 2022-01-26 12:27:52 -08:00
mkinney
1aaa205cc9 Merge pull request #246 from mkinney/update_help
add more info on --ch-set help
2022-01-26 11:22:05 -08:00
Mike Kinney
ff5a0927fa add more info on --ch-set help 2022-01-26 11:16:01 -08:00
mkinney
607127d46e Update regen-protos.sh 2022-01-23 15:15:14 -08:00
mkinney
cf61a5d39d Update update_protobufs.yml 2022-01-23 15:09:44 -08:00
mkinney
69b2599abb Update setup.py 2022-01-23 14:51:38 -08:00
mkinney
533e50de9d Update release.yml 2022-01-23 14:51:21 -08:00
mkinney
12b99f80dc Update release.yml 2022-01-23 14:48:59 -08:00
mkinney
0193ca052f Update setup.py 2022-01-23 14:47:26 -08:00
mkinney
e0af620cbe Merge pull request #245 from mkinney/standalone_readme
add readme.txt to release for standalone zip files
2022-01-23 14:47:06 -08:00
Mike Kinney
80367232ae add readme.txt to release for standalone zip files 2022-01-23 14:44:59 -08:00
mkinney
1c480bd74f Update setup.py 2022-01-23 14:25:01 -08:00
mkinney
ba05de263c Update release.yml 2022-01-23 14:24:48 -08:00
mkinney
f045c3bc2b Update setup.py 2022-01-23 14:17:05 -08:00
mkinney
9ec5f33a85 Update release.yml 2022-01-23 14:16:50 -08:00
mkinney
e1cc657059 Update setup.py 2022-01-23 14:10:58 -08:00
mkinney
9c3dce4bbb Update release.yml 2022-01-23 14:10:43 -08:00
mkinney
5418539275 Update setup.py 2022-01-23 14:04:51 -08:00
mkinney
3103640688 Update release.yml 2022-01-23 14:04:36 -08:00
mkinney
86beb2f212 Update setup.py 2022-01-23 14:03:05 -08:00
mkinney
dd1c96fcba Update release.yml 2022-01-23 14:02:48 -08:00
mkinney
b282baadb7 Update setup.py 2022-01-23 13:55:08 -08:00
mkinney
fccb38fced Update release.yml 2022-01-23 13:54:53 -08:00
mkinney
700a7e27d3 Update setup.py 2022-01-23 13:51:06 -08:00
mkinney
bb1c40c7f8 Update release.yml 2022-01-23 13:50:49 -08:00
mkinney
407490c654 Update setup.py 2022-01-23 13:38:54 -08:00
mkinney
dfd61af346 Update release.yml 2022-01-23 13:38:36 -08:00
mkinney
a85b4ad985 Update setup.py 2022-01-23 13:35:02 -08:00
mkinney
eacffa79fa Update release.yml 2022-01-23 13:34:47 -08:00
mkinney
ca5449f1b8 Update release.yml 2022-01-23 13:21:50 -08:00
mkinney
6751f5bd53 Update release.yml 2022-01-23 13:12:17 -08:00
mkinney
c5c70fe83e Update setup.py 2022-01-23 13:10:06 -08:00
mkinney
0c0cd81253 Update release.yml 2022-01-23 13:09:40 -08:00
mkinney
553a03e40f Update setup.py 2022-01-23 12:53:51 -08:00
mkinney
b50190aeb0 Update release.yml 2022-01-23 12:53:32 -08:00
mkinney
bc231a8a9d Update setup.py 2022-01-23 12:34:36 -08:00
mkinney
c1c9cb8139 Update release.yml 2022-01-23 12:34:12 -08:00
mkinney
0a915e305d Update setup.py 2022-01-23 12:09:55 -08:00
mkinney
308eb1f321 Update release.yml 2022-01-23 12:09:36 -08:00
mkinney
d576c0e30b Update setup.py 2022-01-23 12:01:41 -08:00
mkinney
e63d4c3a30 Update release.yml 2022-01-23 12:01:17 -08:00
mkinney
2041e81101 Update setup.py 2022-01-23 11:49:04 -08:00
mkinney
f396374fa8 Update release.yml 2022-01-23 11:48:13 -08:00
mkinney
1a0db63f32 Merge pull request #244 from mkinney/release_improvements
improve the release process
2022-01-23 11:44:33 -08:00
Mike Kinney
0d32a83e66 improve the release process 2022-01-23 11:41:49 -08:00
mkinney
7ac3328db8 Merge pull request #243 from mkinney/short_name
Short name
2022-01-23 11:25:06 -08:00
Mike Kinney
4f72987a29 add some config tests 2022-01-23 11:22:05 -08:00
Mike Kinney
aa5af53348 add option to configure just the owner short name 2022-01-23 11:17:41 -08:00
Jm Casler
030ee8554c updating proto submodule to latest 2022-01-23 09:10:37 -08:00
14 changed files with 428 additions and 149 deletions

View File

@@ -1,90 +0,0 @@
name: Build and publish standalone executables
on: workflow_dispatch
jobs:
build-and-publish-mac:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Setup code signing
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
run: |
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
security create-keychain -p "$MACOS_KEYCHAIN_PASSWORD" meshtastic.keychain
security default-keychain -s meshtastic.keychain
security unlock-keychain -p "$MACOS_KEYCHAIN_PASSWORD" meshtastic.keychain
security import certificate.p12 -k meshtastic.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_KEYCHAIN_PASSWORD" meshtastic.keychain
- name: Build
env:
MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
run: |
pip install pyinstaller
pip install -r requirements.txt
pip install .
pyinstaller -F -n meshtastic --collect-all meshtastic --codesign-identity "$MACOS_SIGNING_IDENTITY" meshtastic/__main__.py
- uses: actions/upload-artifact@v2
with:
name: meshtastic_mac
path: dist
build-and-publish-ubuntu:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Build
run: |
pip install pyinstaller
pip install -r requirements.txt
pip install .
pyinstaller -F -n meshtastic --collect-all meshtastic meshtastic/__main__.py
- uses: actions/upload-artifact@v2
with:
name: meshtastic_ubuntu
path: dist
build-and-publish-windows:
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Build
run: |
pip install pyinstaller
pip install -r requirements.txt
pip install .
pyinstaller -F -n meshtastic --collect-all meshtastic meshtastic/__main__.py
- uses: actions/upload-artifact@v2
with:
name: meshtastic_windows
path: dist

View File

@@ -1,35 +0,0 @@
name: Publish PyPI
on: workflow_dispatch
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install pypa/build
run: >-
python -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: >-
python -m
build
--sdist
--wheel
--outdir dist/
.
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
username: __token__
password: ${{ secrets.PYPI_API_TOKEN }}

179
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,179 @@
name: Make Release
on:
workflow_dispatch:
inputs:
version:
description: "Release version (Example: 1.0.0, must match 'version' in setup.py)"
required: true
default: '1.0.0'
jobs:
release_create:
runs-on: ubuntu-latest
steps:
- name: Create GitHub release
uses: actions/create-release@v1
id: create_release
with:
draft: true
prerelease: true
release_name: ${{ github.event.inputs.version}}
tag_name: ${{ github.event.inputs.version}}
body: |
Autogenerated by github action, developer should edit as required before publishing...
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
publish_to_pypi:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install pypa/build
run: >-
python -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: >-
python -m
build
--sdist
--wheel
--outdir dist/
.
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
build-and-publish-mac:
runs-on: macos-latest
needs: release_create
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Setup code signing
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }}
run: |
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
security create-keychain -p "$MACOS_KEYCHAIN_PASSWORD" meshtastic.keychain
security default-keychain -s meshtastic.keychain
security unlock-keychain -p "$MACOS_KEYCHAIN_PASSWORD" meshtastic.keychain
security import certificate.p12 -k meshtastic.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_KEYCHAIN_PASSWORD" meshtastic.keychain
- name: Build
env:
MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
run: |
pip install pyinstaller
pip install -r requirements.txt
pip install .
pyinstaller -F -n meshtastic --collect-all meshtastic --codesign-identity "$MACOS_SIGNING_IDENTITY" meshtastic/__main__.py
- name: Add mac to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release_create.outputs.upload_url }}
asset_path: dist/meshtastic
asset_name: meshtastic_mac
asset_content_type: application/zip
build-and-publish-ubuntu:
runs-on: ubuntu-latest
needs: release_create
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Build
run: |
pip install pyinstaller
pip install -r requirements.txt
pip install .
pyinstaller -F -n meshtastic --collect-all meshtastic meshtastic/__main__.py
- name: Add ubuntu to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release_create.outputs.upload_url }}
asset_path: dist/meshtastic
asset_name: meshtastic_ubuntu
asset_content_type: application/zip
- name: Add readme.txt to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release_create.outputs.upload_url }}
asset_path: standalone_readme.txt
asset_name: readme.txt
asset_content_type: text/plain
build-and-publish-windows:
runs-on: windows-latest
needs: release_create
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Build
run: |
pip install pyinstaller
pip install -r requirements.txt
pip install .
pyinstaller -F -n meshtastic --collect-all meshtastic meshtastic/__main__.py
- name: Add windows to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.release_create.outputs.upload_url }}
asset_path: dist/meshtastic.exe
asset_name: meshtastic_windows
asset_content_type: application/zip

View File

@@ -15,6 +15,17 @@ jobs:
run: |
git pull --recurse-submodules
git submodule update --remote --recursive
- name: Download nanopb
run: |
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.4-linux-x86.tar.gz
tar xvzf nanopb-0.4.4-linux-x86.tar.gz
mv nanopb-0.4.4-linux-x86 nanopb-0.4.4
- name: Re-generate protocol buffers
run: |
./bin/regen-protos.sh
- name: Commit update
run: |
git config --global user.name 'github-actions'

View File

@@ -5,11 +5,11 @@
# workaround for import bug in protoc https://github.com/protocolbuffers/protobuf/issues/1491#issuecomment-690618628
if [[ $OSTYPE == 'darwin'* ]]; then
sed -i -E 's/^\(import.*_pb2\)/from . \1/' meshtastic/*.py
sed -i '' -E 's/^\(import.*_pb2\)/from . \1/' meshtastic/*.py
# automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/Meshtastic-protobufs/issues/27)
sed -i '' -E "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py
else
sed -i -E 's/^import.*_pb2/from . \0/' meshtastic/*.py
sed -i -e 's/^import.*_pb2/from . \0/' meshtastic/*.py
# automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/Meshtastic-protobufs/issues/27)
sed -i -e "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py
fi
# automate the current workaround (may be related to Meshtastic-protobufs issue #27 https://github.com/meshtastic/Meshtastic-protobufs/issues/27)
sed -i '' -e "s/^None = 0/globals()['None'] = 0/" meshtastic/mesh_pb2.py

View File

@@ -1,5 +1,6 @@
# example config using camelCase keys
owner: Bob TBeam
ownerShort: BOB
channelUrl: https://www.meshtastic.org/d/#CgUYAyIBAQ

View File

@@ -1,5 +1,6 @@
# example configuration file with snake_case keys
owner: Bob TBeam
owner_short: BOB
channel_url: https://www.meshtastic.org/d/#CgUYAyIBAQ

View File

@@ -195,6 +195,11 @@ def onConnected(interface):
print(f"Setting device owner to {args.set_owner}")
interface.getNode(args.dest).setOwner(args.set_owner)
if args.set_owner_short:
closeNow = True
print(f"Setting device owner short to {args.set_owner_short}")
interface.getNode(args.dest).setOwner(long_name=None, short_name=args.set_owner_short)
if args.pos_fields:
# If --pos-fields invoked with args, set position fields
closeNow = True
@@ -296,12 +301,11 @@ def onConnected(interface):
print(f"Reading GPIO mask 0x{bitmask:x} from {args.dest}")
interface.mask = bitmask
rhc.readGPIOs(args.dest, bitmask, None)
if not interface.noProto:
# wait up to X seconds for a response
for _ in range(10):
time.sleep(1)
if interface.gotResponse:
break
# wait up to X seconds for a response
for _ in range(10):
time.sleep(1)
if interface.gotResponse:
break
logging.debug(f'end of gpio_rd')
if args.gpio_watch:
@@ -332,6 +336,14 @@ def onConnected(interface):
print(f"Setting device owner to {configuration['owner']}")
interface.getNode(args.dest).setOwner(configuration['owner'])
if 'owner_short' in configuration:
print(f"Setting device owner short to {configuration['owner_short']}")
interface.getNode(args.dest).setOwner(long_name=None, short_owner=configuration['owner_short'])
if 'ownerShort' in configuration:
print(f"Setting device owner short to {configuration['ownerShort']}")
interface.getNode(args.dest).setOwner(long_name=None, short_owner=configuration['ownerShort'])
if 'channel_url' in configuration:
print("Setting channel url to", configuration['channel_url'])
interface.getNode(args.dest).setURL(configuration['channel_url'])
@@ -569,6 +581,7 @@ def subscribe():
def export_config(interface):
"""used in--export-config"""
owner = interface.getLongName()
owner_short = interface.getShortName()
channel_url = interface.localNode.getURL()
myinfo = interface.getMyNodeInfo()
pos = myinfo.get('position')
@@ -583,6 +596,8 @@ def export_config(interface):
config = "# start of Meshtastic configure yaml\n"
if owner:
config += f"owner: {owner}\n\n"
if owner_short:
config += f"owner_short: {owner_short}\n\n"
if channel_url:
if Globals.getInstance().get_camel_case():
config += f"channelUrl: {channel_url}\n\n"
@@ -765,7 +780,12 @@ def initParser():
"--ch-disable", help="Disable the specified channel", action="store_true", dest="ch_disable", default=False)
parser.add_argument(
"--ch-set", help="Set a channel parameter", nargs=2, action='append')
"--ch-set", help=("Set a channel parameter. To see channel settings available:'--ch-set all all --ch-index 0'. "
"Can set the 'psk' using this command. To disable encryption on primary channel:'--ch-set psk none --ch-index 0'. "
"To set encryption with a new random key on second channel:'--ch-set psk random --ch-index 1'. "
"To set encryption back to the default:'--ch-set default --ch-index 0'. To set encryption with your "
"own key: '--ch-set psk 0x1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b1a1a1a1a2b2b2b2b --ch-index 0'."),
nargs=2, action='append')
parser.add_argument(
"--ch-longslow", help="Change to the long-range and slow channel", action='store_true')
@@ -785,10 +805,12 @@ def initParser():
parser.add_argument(
"--ch-shortfast", help="Change to the short-range and fast channel", action='store_true')
parser.add_argument(
"--set-owner", help="Set device owner name", action="store")
parser.add_argument(
"--set-owner-short", help="Set device owner short name", action="store")
parser.add_argument(
"--set-team", help="Set team affiliation (an invalid team will list valid values)", action="store")

View File

@@ -10,8 +10,17 @@ def onGPIOreceive(packet, interface):
"""Callback for received GPIO responses
"""
logging.debug(f"packet:{packet} interface:{interface}")
gpioValue = 0
hw = packet["decoded"]["remotehw"]
gpioValue = hw["gpioValue"]
if "gpioValue" in hw:
gpioValue = hw["gpioValue"]
else:
if not "gpioMask" in hw:
# we did get a reply, but due to protobufs, 0 for numeric value is not sent
# see https://developers.google.com/protocol-buffers/docs/proto3#default
# so, we set it here
gpioValue = 0
#print(f'mask:{interface.mask}')
value = int(gpioValue) & int(interface.mask)
print(f'Received RemoteHardware typ={hw["typ"]}, gpio_value={gpioValue} value={value}')

View File

@@ -425,6 +425,23 @@ def test_main_set_owner_to_bob(capsys):
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_set_owner_short_to_bob(capsys):
"""Test --set-owner-short bob"""
sys.argv = ['', '--set-owner-short', 'bob']
Globals.getInstance().set_args(sys.argv)
iface = MagicMock(autospec=SerialInterface)
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
main()
out, err = capsys.readouterr()
assert re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'Setting device owner short to bob', out, re.MULTILINE)
assert err == ''
mo.assert_called()
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_set_ham_to_KI123(capsys):
@@ -913,6 +930,7 @@ def test_main_configure_with_snake_case(capsys):
out, err = capsys.readouterr()
assert re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'Setting device owner', out, re.MULTILINE)
assert re.search(r'Setting device owner short', out, re.MULTILINE)
assert re.search(r'Setting channel url', out, re.MULTILINE)
assert re.search(r'Fixing altitude', out, re.MULTILINE)
assert re.search(r'Fixing latitude', out, re.MULTILINE)
@@ -940,6 +958,7 @@ def test_main_configure_with_camel_case_keys(capsys):
out, err = capsys.readouterr()
assert re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'Setting device owner', out, re.MULTILINE)
assert re.search(r'Setting device owner short', out, re.MULTILINE)
assert re.search(r'Setting channel url', out, re.MULTILINE)
assert re.search(r'Fixing altitude', out, re.MULTILINE)
assert re.search(r'Fixing latitude', out, re.MULTILINE)
@@ -1604,6 +1623,7 @@ def test_main_export_config(capsys):
iface = MagicMock(autospec=SerialInterface)
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
mo.getLongName.return_value = 'foo'
mo.getShortName.return_value = 'oof'
mo.localNode.getURL.return_value = 'bar'
mo.getMyNodeInfo().get.return_value = { 'latitudeI': 1100000000, 'longitudeI': 1200000000,
'altitude': 100, 'batteryLevel': 34, 'latitude': 110.0,
@@ -1620,6 +1640,7 @@ position_flags: 35"""
assert not re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'owner: foo', out, re.MULTILINE)
assert re.search(r'owner_short: oof', out, re.MULTILINE)
assert re.search(r'channel_url: bar', out, re.MULTILINE)
assert re.search(r'location:', out, re.MULTILINE)
assert re.search(r'lat: 110.0', out, re.MULTILINE)
@@ -1734,18 +1755,18 @@ def test_main_gpio_rd_no_dest(capsys):
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
@patch('time.sleep')
def test_main_gpio_rd(caplog, capsys):
"""Test --gpio_rd with a named gpio channel"""
# Note: On the Heltec v2.1, there is a GPIO pin GPIO 13 that does not have a
# red arrow (meaning ok to use for our purposes)
# See https://resource.heltec.cn/download/WiFi_LoRa_32/WIFI_LoRa_32_V2.pdf
# To find out the mask for GPIO 13, let us assign n as 13.
# 1. Subtract 1 from n (n is now 12)
# 2. Find the 2^n or 2^12 (4096)
# 3. Convert 4096 decimal to hex (0x1000)
# 1. Find the 2^n or 2^13 (8192)
# 2. Convert 8192 decimal to hex (0x2000)
# You can use python:
# >>> print(hex(2**12))
# 0x1000
# >>> print(hex(2**13))
# 0x2000
sys.argv = ['', '--gpio-rd', '0x1000', '--dest', '!1234']
Globals.getInstance().set_args(sys.argv)
@@ -1775,6 +1796,52 @@ def test_main_gpio_rd(caplog, capsys):
}
}
iface = MagicMock(autospec=SerialInterface)
iface.localNode.getChannelByName.return_value = channel
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
with caplog.at_level(logging.DEBUG):
main()
onGPIOreceive(packet, mo)
out, err = capsys.readouterr()
assert re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'Reading GPIO mask 0x1000 ', out, re.MULTILINE)
assert re.search(r'Received RemoteHardware typ=READ_GPIOS_REPLY, gpio_value=4096', out, re.MULTILINE)
assert err == ''
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
@patch('time.sleep')
def test_main_gpio_rd_with_no_gpioMask(caplog, capsys):
"""Test --gpio_rd with a named gpio channel"""
sys.argv = ['', '--gpio-rd', '0x1000', '--dest', '!1234']
Globals.getInstance().set_args(sys.argv)
channel = Channel(index=1, role=1)
channel.settings.modem_config = 3
channel.settings.psk = b'\x01'
# Note: Intentionally do not have gpioValue in response as that is the
# default value
packet = {
'from': 682968668,
'to': 682968612,
'channel': 1,
'decoded': {
'portnum': 'REMOTE_HARDWARE_APP',
'payload': b'\x08\x05\x18\x80 ',
'requestId': 1629980484,
'remotehw': {
'typ': 'READ_GPIOS_REPLY',
'raw': 'faked',
'id': 1693085229,
'rxTime': 1640294262,
'rxSnr': 4.75,
'hopLimit': 3,
'wantAck': True,
}
}
}
iface = MagicMock(autospec=SerialInterface)
iface.localNode.getChannelByName.return_value = channel
@@ -1782,14 +1849,112 @@ def test_main_gpio_rd(caplog, capsys):
with caplog.at_level(logging.DEBUG):
main()
onGPIOreceive(packet, mo)
assert re.search(r'readGPIOs nodeid:!1234 mask:4096', caplog.text, re.MULTILINE)
out, err = capsys.readouterr()
assert re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'Reading GPIO mask 0x1000 ', out, re.MULTILINE)
assert re.search(r'Received RemoteHardware typ=READ_GPIOS_REPLY, gpio_value=4096', out, re.MULTILINE)
assert re.search(r'Received RemoteHardware typ=READ_GPIOS_REPLY, gpio_value=0', out, re.MULTILINE)
assert err == ''
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_gpio_watch(caplog, capsys):
"""Test --gpio_watch with a named gpio channel"""
sys.argv = ['', '--gpio-watch', '0x1000', '--dest', '!1234']
Globals.getInstance().set_args(sys.argv)
def my_sleep(amount):
print(f'{amount}')
sys.exit(3)
channel = Channel(index=1, role=1)
channel.settings.modem_config = 3
channel.settings.psk = b'\x01'
packet = {
'from': 682968668,
'to': 682968612,
'channel': 1,
'decoded': {
'portnum': 'REMOTE_HARDWARE_APP',
'payload': b'\x08\x05\x18\x80 ',
'requestId': 1629980484,
'remotehw': {
'typ': 'READ_GPIOS_REPLY',
'gpioValue': '4096',
'raw': 'faked',
'id': 1693085229,
'rxTime': 1640294262,
'rxSnr': 4.75,
'hopLimit': 3,
'wantAck': True,
}
}
}
with patch('time.sleep', side_effect=my_sleep):
with pytest.raises(SystemExit) as pytest_wrapped_e:
iface = MagicMock(autospec=SerialInterface)
iface.localNode.getChannelByName.return_value = channel
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
with caplog.at_level(logging.DEBUG):
main()
onGPIOreceive(packet, mo)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 3
out, err = capsys.readouterr()
assert re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'Watching GPIO mask 0x1000 ', out, re.MULTILINE)
assert err == ''
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_gpio_wrb(caplog, capsys):
"""Test --gpio_wrb with a named gpio channel"""
sys.argv = ['', '--gpio-wrb', '4', '1', '--dest', '!1234']
Globals.getInstance().set_args(sys.argv)
channel = Channel(index=1, role=1)
channel.settings.modem_config = 3
channel.settings.psk = b'\x01'
packet = {
'from': 682968668,
'to': 682968612,
'channel': 1,
'decoded': {
'portnum': 'REMOTE_HARDWARE_APP',
'payload': b'\x08\x05\x18\x80 ',
'requestId': 1629980484,
'remotehw': {
'typ': 'READ_GPIOS_REPLY',
'gpioValue': '16',
'raw': 'faked',
'id': 1693085229,
'rxTime': 1640294262,
'rxSnr': 4.75,
'hopLimit': 3,
'wantAck': True,
}
}
}
iface = MagicMock(autospec=SerialInterface)
iface.localNode.getChannelByName.return_value = channel
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
with caplog.at_level(logging.DEBUG):
main()
onGPIOreceive(packet, mo)
out, err = capsys.readouterr()
assert re.search(r'Connected to radio', out, re.MULTILINE)
assert re.search(r'Writing GPIO mask 0x10 with value 0x10 to !1234', out, re.MULTILINE)
assert re.search(r'Received RemoteHardware typ=READ_GPIOS_REPLY, gpio_value=16 value=0', out, re.MULTILINE)
assert err == ''
@pytest.mark.unit
@pytest.mark.usefixtures("reset_globals")
def test_main_getPref_valid_field(capsys):

View File

@@ -55,6 +55,15 @@ def test_setOwner_and_team(caplog):
assert re.search(r'p.set_owner.team:1', caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_setOwnerShort(caplog):
"""Test setOwner"""
anode = Node('foo', 'bar', noProto=True)
with caplog.at_level(logging.DEBUG):
anode.setOwner(long_name=None, short_name='123')
assert re.search(r'p.set_owner.short_name:123:', caplog.text, re.MULTILINE)
@pytest.mark.unit
def test_setOwner_no_short_name(caplog):
"""Test setOwner"""

2
proto

Submodule proto updated: 62cb78fcbe...07ed86d8b4

View File

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

7
standalone_readme.txt Normal file
View File

@@ -0,0 +1,7 @@
readme.txt for single standalone executable zip files that can be
downloaded from https://github.com/meshtastic/Meshtastic-python/releases
If you do not want to install python and/or the python libraries, you can download one of these
zip files to run the Meshtastic command line interface (CLI) as a standalone executable.
See https://meshtastic.org/docs/software/python/python-standalone for more info.