mirror of
https://github.com/meshtastic/python.git
synced 2025-12-26 09:27:52 -05:00
Compare commits
4 Commits
2.6.1
...
revert-753
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfc9547ffc | ||
|
|
ee0f73a20e | ||
|
|
2e73fe310c | ||
|
|
d4bc39153a |
@@ -46,12 +46,7 @@ class SerialInterface(StreamInterface):
|
||||
|
||||
logging.debug(f"Connecting to {self.devPath}")
|
||||
|
||||
# set port to None to prevent automatically opening
|
||||
self.stream = serial.Serial(
|
||||
port=None, baudrate=115200, exclusive=True, timeout=0.5, write_timeout=0
|
||||
)
|
||||
|
||||
# first we need to clear HUPCL (UNIX) or clear RTS/DTR (Windows) so the device will not reboot based on RTS and/or DTR
|
||||
# first we need to set the HUPCL so the device will not reboot based on RTS and/or DTR
|
||||
# see https://github.com/pyserial/pyserial/issues/124
|
||||
if platform.system() != "Windows":
|
||||
with open(self.devPath, encoding="utf8") as f:
|
||||
@@ -60,14 +55,10 @@ class SerialInterface(StreamInterface):
|
||||
termios.tcsetattr(f, termios.TCSAFLUSH, attrs)
|
||||
f.close()
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
self.stream.rts = 0
|
||||
self.stream.dtr = 0
|
||||
|
||||
# set proper port and open now that we've worked-around RTS/DTR issues
|
||||
self.stream.port = self.devPath
|
||||
self.stream.open()
|
||||
|
||||
self.stream = serial.Serial(
|
||||
self.devPath, 115200, exclusive=True, timeout=0.5, write_timeout=0
|
||||
)
|
||||
self.stream.flush() # type: ignore[attr-defined]
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
"""TCPInterface class for interfacing with http endpoint
|
||||
"""
|
||||
# pylint: disable=R0917
|
||||
import contextlib
|
||||
import logging
|
||||
import socket
|
||||
from typing import Optional, cast
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
from meshtastic.stream_interface import StreamInterface
|
||||
|
||||
@@ -35,52 +37,63 @@ class TCPInterface(StreamInterface):
|
||||
self.socket: Optional[socket.socket] = None
|
||||
|
||||
if connectNow:
|
||||
logging.debug(f"Connecting to {hostname}") # type: ignore[str-bytes-safe]
|
||||
server_address: tuple[str, int] = (hostname, portNumber)
|
||||
sock: Optional[socket.socket] = socket.create_connection(server_address)
|
||||
self.socket = sock
|
||||
self.myConnect()
|
||||
else:
|
||||
self.socket = None
|
||||
|
||||
StreamInterface.__init__(
|
||||
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow, noNodes=noNodes
|
||||
)
|
||||
super().__init__(debugOut=debugOut, noProto=noProto, connectNow=connectNow, noNodes=noNodes)
|
||||
|
||||
def _socket_shutdown(self) -> None:
|
||||
"""Shutdown the socket.
|
||||
Note: Broke out this line so the exception could be unit tested.
|
||||
"""
|
||||
if self.socket: #mian: please check that this should be "if self.socket:"
|
||||
cast(socket.socket, self.socket).shutdown(socket.SHUT_RDWR)
|
||||
if self.socket is not None:
|
||||
self.socket.shutdown(socket.SHUT_RDWR)
|
||||
|
||||
def myConnect(self) -> None:
|
||||
"""Connect to socket"""
|
||||
server_address: tuple[str, int] = (self.hostname, self.portNumber)
|
||||
sock: Optional[socket.socket] = socket.create_connection(server_address)
|
||||
self.socket = sock
|
||||
logging.debug(f"Connecting to {self.hostname}") # type: ignore[str-bytes-safe]
|
||||
server_address = (self.hostname, self.portNumber)
|
||||
self.socket = socket.create_connection(server_address)
|
||||
|
||||
def close(self) -> None:
|
||||
"""Close a connection to the device"""
|
||||
logging.debug("Closing TCP stream")
|
||||
StreamInterface.close(self)
|
||||
super().close()
|
||||
# Sometimes the socket read might be blocked in the reader thread.
|
||||
# Therefore we force the shutdown by closing the socket here
|
||||
self._wantExit: bool = True
|
||||
if not self.socket is None:
|
||||
try:
|
||||
self._wantExit = True
|
||||
if self.socket is not None:
|
||||
with contextlib.suppress(Exception): # Ignore errors in shutdown, because we might have a race with the server
|
||||
self._socket_shutdown()
|
||||
except:
|
||||
pass # Ignore errors in shutdown, because we might have a race with the server
|
||||
self.socket.close()
|
||||
|
||||
self.socket = None
|
||||
|
||||
def _writeBytes(self, b: bytes) -> None:
|
||||
"""Write an array of bytes to our stream and flush"""
|
||||
if self.socket:
|
||||
if self.socket is not None:
|
||||
self.socket.send(b)
|
||||
|
||||
def _readBytes(self, length) -> Optional[bytes]:
|
||||
"""Read an array of bytes from our stream"""
|
||||
if self.socket:
|
||||
return self.socket.recv(length)
|
||||
else:
|
||||
return None
|
||||
if self.socket is not None:
|
||||
data = self.socket.recv(length)
|
||||
# empty byte indicates a disconnected socket,
|
||||
# we need to handle it to avoid an infinite loop reading from null socket
|
||||
if data == b'':
|
||||
logging.debug("dead socket, re-connecting")
|
||||
# cleanup and reconnect socket without breaking reader thread
|
||||
with contextlib.suppress(Exception):
|
||||
self._socket_shutdown()
|
||||
self.socket.close()
|
||||
self.socket = None
|
||||
time.sleep(1)
|
||||
self.myConnect()
|
||||
self._startConfig()
|
||||
return None
|
||||
return data
|
||||
|
||||
# no socket, break reader thread
|
||||
self._wantExit = True
|
||||
return None
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "meshtastic"
|
||||
version = "2.6.1"
|
||||
version = "2.6.2a0"
|
||||
description = "Python API & client shell for talking to Meshtastic devices"
|
||||
authors = ["Meshtastic Developers <contact@meshtastic.org>"]
|
||||
license = "GPL-3.0-only"
|
||||
|
||||
Reference in New Issue
Block a user