mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge pull request #1783 from openmv/scripts_format
scripts/libraries: Format RPC/RTSP libraries.
This commit is contained in:
commit
dfee4d1b98
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
import gc, network, omv, pyb, select, socket, stm, struct
|
import gc, network, omv, pyb, select, socket, stm, struct
|
||||||
|
|
||||||
class rpc:
|
|
||||||
|
|
||||||
|
class rpc:
|
||||||
_COMMAND_HEADER_PACKET_MAGIC = 0x1209
|
_COMMAND_HEADER_PACKET_MAGIC = 0x1209
|
||||||
_COMMAND_DATA_PACKET_MAGIC = 0xABD1
|
_COMMAND_DATA_PACKET_MAGIC = 0xABD1
|
||||||
_RESULT_HEADER_PACKET_MAGIC = 0x9021
|
_RESULT_HEADER_PACKET_MAGIC = 0x9021
|
||||||
@ -20,7 +20,8 @@ class rpc:
|
|||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for i in range(size):
|
for i in range(size):
|
||||||
crc ^= d[i] << 8
|
crc ^= d[i] << 8
|
||||||
for j in range(8): crc = (crc << 1) ^ (0x1021 if crc & 0x8000 else 0)
|
for j in range(8):
|
||||||
|
crc = (crc << 1) ^ (0x1021 if crc & 0x8000 else 0)
|
||||||
return crc & 0xFFFF
|
return crc & 0xFFFF
|
||||||
|
|
||||||
@micropython.viper
|
@micropython.viper
|
||||||
@ -35,16 +36,19 @@ class rpc:
|
|||||||
@micropython.viper
|
@micropython.viper
|
||||||
def _zero(self, buff, size: int): # private
|
def _zero(self, buff, size: int): # private
|
||||||
d = ptr8(buff)
|
d = ptr8(buff)
|
||||||
for i in range(size): d[i] = 0
|
for i in range(size):
|
||||||
|
d[i] = 0
|
||||||
|
|
||||||
@micropython.viper
|
@micropython.viper
|
||||||
def _same(self, data, size: int) -> bool: # private
|
def _same(self, data, size: int) -> bool: # private
|
||||||
if not size: return False
|
if not size:
|
||||||
|
return False
|
||||||
d = ptr8(data)
|
d = ptr8(data)
|
||||||
old = d[0]
|
old = d[0]
|
||||||
for i in range(1, size):
|
for i in range(1, size):
|
||||||
new = d[i]
|
new = d[i]
|
||||||
if new != old: return False
|
if new != old:
|
||||||
|
return False
|
||||||
old = new
|
old = new
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -99,43 +103,63 @@ class rpc:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def stream_reader(self, call_back, queue_depth=1, read_timeout_ms=5000): # public
|
def stream_reader(self, call_back, queue_depth=1, read_timeout_ms=5000): # public
|
||||||
try: self._stream_put_bytes(self._set_packet(0xEDF6, struct.pack("<I", queue_depth)), 1000)
|
try:
|
||||||
except OSError: return
|
self._stream_put_bytes(self._set_packet(0xEDF6, struct.pack("<I", queue_depth)), 1000)
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
tx_lfsr = 255
|
tx_lfsr = 255
|
||||||
while True:
|
while True:
|
||||||
packet = self._stream_get_bytes(bytearray(8), 1000)
|
packet = self._stream_get_bytes(bytearray(8), 1000)
|
||||||
if packet is None: return
|
if packet is None:
|
||||||
|
return
|
||||||
magic = packet[0] | (packet[1] << 8)
|
magic = packet[0] | (packet[1] << 8)
|
||||||
crc = packet[-2] | (packet[-1] << 8)
|
crc = packet[-2] | (packet[-1] << 8)
|
||||||
if magic != 0x542E and crc != self.__crc_16(packet, len(packet) - 2): return
|
if magic != 0x542E and crc != self.__crc_16(packet, len(packet) - 2):
|
||||||
data = self._stream_get_bytes(bytearray(struct.unpack("<I", packet[2:-2])[0]), read_timeout_ms)
|
return
|
||||||
if data is None: return
|
data = self._stream_get_bytes(
|
||||||
|
bytearray(struct.unpack("<I", packet[2:-2])[0]), read_timeout_ms
|
||||||
|
)
|
||||||
|
if data is None:
|
||||||
|
return
|
||||||
call_back(data)
|
call_back(data)
|
||||||
try: self._stream_put_bytes(struct.pack("<B", tx_lfsr), 1000)
|
try:
|
||||||
except OSError: return
|
self._stream_put_bytes(struct.pack("<B", tx_lfsr), 1000)
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
tx_lfsr = (tx_lfsr >> 1) ^ (0xB8 if tx_lfsr & 1 else 0x00)
|
tx_lfsr = (tx_lfsr >> 1) ^ (0xB8 if tx_lfsr & 1 else 0x00)
|
||||||
|
|
||||||
def stream_writer(self, call_back, write_timeout_ms=5000): # public
|
def stream_writer(self, call_back, write_timeout_ms=5000): # public
|
||||||
packet = self._stream_get_bytes(bytearray(8), 1000)
|
packet = self._stream_get_bytes(bytearray(8), 1000)
|
||||||
if packet is None: return
|
if packet is None:
|
||||||
|
return
|
||||||
magic = packet[0] | (packet[1] << 8)
|
magic = packet[0] | (packet[1] << 8)
|
||||||
crc = packet[-2] | (packet[-1] << 8)
|
crc = packet[-2] | (packet[-1] << 8)
|
||||||
if magic != 0xEDF6 and crc != self.__crc_16(packet, len(packet) - 2): return
|
if magic != 0xEDF6 and crc != self.__crc_16(packet, len(packet) - 2):
|
||||||
queue_depth = max(min(struct.unpack("<I", packet[2:-2])[0], self._stream_writer_queue_depth_max), 1)
|
return
|
||||||
|
queue_depth = max(
|
||||||
|
min(struct.unpack("<I", packet[2:-2])[0], self._stream_writer_queue_depth_max), 1
|
||||||
|
)
|
||||||
rx_lfsr = 255
|
rx_lfsr = 255
|
||||||
credits = queue_depth
|
credits = queue_depth
|
||||||
while True:
|
while True:
|
||||||
if credits <= (queue_depth // 2):
|
if credits <= (queue_depth // 2):
|
||||||
data = self._stream_get_bytes(bytearray(1), 1000)
|
data = self._stream_get_bytes(bytearray(1), 1000)
|
||||||
if data is None or data[0] != rx_lfsr: return
|
if data is None or data[0] != rx_lfsr:
|
||||||
|
return
|
||||||
rx_lfsr = (rx_lfsr >> 1) ^ (0xB8 if rx_lfsr & 1 else 0x00)
|
rx_lfsr = (rx_lfsr >> 1) ^ (0xB8 if rx_lfsr & 1 else 0x00)
|
||||||
credits += 1
|
credits += 1
|
||||||
if credits > 0:
|
if credits > 0:
|
||||||
data = call_back()
|
data = call_back()
|
||||||
try: self._stream_put_bytes(self._set_packet(0x542E, struct.pack("<I", len(data))), 1000)
|
try:
|
||||||
except OSError: return
|
self._stream_put_bytes(
|
||||||
try: self._stream_put_bytes(data, write_timeout_ms)
|
self._set_packet(0x542E, struct.pack("<I", len(data))), 1000
|
||||||
except OSError: return
|
)
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
self._stream_put_bytes(data, write_timeout_ms)
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
credits -= 1
|
credits -= 1
|
||||||
|
|
||||||
def _stream_get_bytes(self, buff, timeout_ms): # protected
|
def _stream_get_bytes(self, buff, timeout_ms): # protected
|
||||||
@ -144,8 +168,8 @@ class rpc:
|
|||||||
def _stream_put_bytes(self, data, timeout_ms): # protected
|
def _stream_put_bytes(self, data, timeout_ms): # protected
|
||||||
self.put_bytes(data, timeout_ms)
|
self.put_bytes(data, timeout_ms)
|
||||||
|
|
||||||
class rpc_master(rpc):
|
|
||||||
|
|
||||||
|
class rpc_master(rpc):
|
||||||
def __init__(self): # private
|
def __init__(self): # private
|
||||||
rpc.__init__(self)
|
rpc.__init__(self)
|
||||||
self.__in_command_header_buf = self._get_packet_pre_alloc()
|
self.__in_command_header_buf = self._get_packet_pre_alloc()
|
||||||
@ -161,7 +185,9 @@ class rpc_master(rpc):
|
|||||||
def __put_command(self, command, data, timeout): # private
|
def __put_command(self, command, data, timeout): # private
|
||||||
self._put_short_timeout = self._put_short_timeout_reset
|
self._put_short_timeout = self._put_short_timeout_reset
|
||||||
self._get_short_timeout = self._get_short_timeout_reset
|
self._get_short_timeout = self._get_short_timeout_reset
|
||||||
out_header = self._set_packet(self._COMMAND_HEADER_PACKET_MAGIC, struct.pack("<II", command, len(data)))
|
out_header = self._set_packet(
|
||||||
|
self._COMMAND_HEADER_PACKET_MAGIC, struct.pack("<II", command, len(data))
|
||||||
|
)
|
||||||
out_data = self._set_packet(self._COMMAND_DATA_PACKET_MAGIC, data)
|
out_data = self._set_packet(self._COMMAND_DATA_PACKET_MAGIC, data)
|
||||||
start = pyb.millis()
|
start = pyb.millis()
|
||||||
while pyb.elapsed_millis(start) < timeout:
|
while pyb.elapsed_millis(start) < timeout:
|
||||||
@ -170,9 +196,23 @@ class rpc_master(rpc):
|
|||||||
self._zero(self.__in_command_data_buf[0], len(self.__in_command_data_buf[0]))
|
self._zero(self.__in_command_data_buf[0], len(self.__in_command_data_buf[0]))
|
||||||
self._flush()
|
self._flush()
|
||||||
self.put_bytes(out_header, self._put_short_timeout)
|
self.put_bytes(out_header, self._put_short_timeout)
|
||||||
if self._get_packet(self._COMMAND_HEADER_PACKET_MAGIC, self.__in_command_header_buf, self._get_short_timeout) is not None:
|
if (
|
||||||
|
self._get_packet(
|
||||||
|
self._COMMAND_HEADER_PACKET_MAGIC,
|
||||||
|
self.__in_command_header_buf,
|
||||||
|
self._get_short_timeout,
|
||||||
|
)
|
||||||
|
is not None
|
||||||
|
):
|
||||||
self.put_bytes(out_data, self._put_long_timeout)
|
self.put_bytes(out_data, self._put_long_timeout)
|
||||||
if self._get_packet(self._COMMAND_DATA_PACKET_MAGIC, self.__in_command_data_buf, self._get_short_timeout) is not None:
|
if (
|
||||||
|
self._get_packet(
|
||||||
|
self._COMMAND_DATA_PACKET_MAGIC,
|
||||||
|
self.__in_command_data_buf,
|
||||||
|
self._get_short_timeout,
|
||||||
|
)
|
||||||
|
is not None
|
||||||
|
):
|
||||||
return True
|
return True
|
||||||
# Avoid timeout livelocking.
|
# Avoid timeout livelocking.
|
||||||
self._put_short_timeout = min((self._put_short_timeout * 4) // 3, timeout)
|
self._put_short_timeout = min((self._put_short_timeout * 4) // 3, timeout)
|
||||||
@ -188,11 +228,17 @@ class rpc_master(rpc):
|
|||||||
self._zero(self.__in_result_header_buf[0], len(self.__in_result_header_buf[0]))
|
self._zero(self.__in_result_header_buf[0], len(self.__in_result_header_buf[0]))
|
||||||
self._flush()
|
self._flush()
|
||||||
self.put_bytes(self.__out_result_header_ack, self._put_short_timeout)
|
self.put_bytes(self.__out_result_header_ack, self._put_short_timeout)
|
||||||
packet = self._get_packet(self._RESULT_HEADER_PACKET_MAGIC, self.__in_result_header_buf, self._get_short_timeout)
|
packet = self._get_packet(
|
||||||
|
self._RESULT_HEADER_PACKET_MAGIC,
|
||||||
|
self.__in_result_header_buf,
|
||||||
|
self._get_short_timeout,
|
||||||
|
)
|
||||||
if packet is not None:
|
if packet is not None:
|
||||||
in_result_data_buf = self._get_packet_pre_alloc(struct.unpack("<I", packet)[0])
|
in_result_data_buf = self._get_packet_pre_alloc(struct.unpack("<I", packet)[0])
|
||||||
self.put_bytes(self.__out_result_data_ack, self._put_short_timeout)
|
self.put_bytes(self.__out_result_data_ack, self._put_short_timeout)
|
||||||
dat_packet = self._get_packet(self._RESULT_DATA_PACKET_MAGIC, in_result_data_buf, self._get_long_timeout)
|
dat_packet = self._get_packet(
|
||||||
|
self._RESULT_DATA_PACKET_MAGIC, in_result_data_buf, self._get_long_timeout
|
||||||
|
)
|
||||||
if dat_packet is not None:
|
if dat_packet is not None:
|
||||||
return dat_packet
|
return dat_packet
|
||||||
# Avoid timeout livelocking.
|
# Avoid timeout livelocking.
|
||||||
@ -201,10 +247,14 @@ class rpc_master(rpc):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def call(self, name, data=bytes(), send_timeout=1000, recv_timeout=1000): # public
|
def call(self, name, data=bytes(), send_timeout=1000, recv_timeout=1000): # public
|
||||||
return self.__get_result(recv_timeout) if self.__put_command(self._hash(name, len(name)), data, send_timeout) else None
|
return (
|
||||||
|
self.__get_result(recv_timeout)
|
||||||
|
if self.__put_command(self._hash(name, len(name)), data, send_timeout)
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class rpc_slave(rpc):
|
class rpc_slave(rpc):
|
||||||
|
|
||||||
def __init__(self): # private
|
def __init__(self): # private
|
||||||
self.__dict = {}
|
self.__dict = {}
|
||||||
self.__schedule_cb = None
|
self.__schedule_cb = None
|
||||||
@ -228,12 +278,18 @@ class rpc_slave(rpc):
|
|||||||
gc.collect() # Avoid collection during the transfer.
|
gc.collect() # Avoid collection during the transfer.
|
||||||
self._zero(self.__in_command_header_buf[0], len(self.__in_command_header_buf[0]))
|
self._zero(self.__in_command_header_buf[0], len(self.__in_command_header_buf[0]))
|
||||||
self._flush()
|
self._flush()
|
||||||
packet = self._get_packet(self._COMMAND_HEADER_PACKET_MAGIC, self.__in_command_header_buf, self._get_short_timeout)
|
packet = self._get_packet(
|
||||||
|
self._COMMAND_HEADER_PACKET_MAGIC,
|
||||||
|
self.__in_command_header_buf,
|
||||||
|
self._get_short_timeout,
|
||||||
|
)
|
||||||
if packet is not None:
|
if packet is not None:
|
||||||
command, datalen = struct.unpack("<II", packet)
|
command, datalen = struct.unpack("<II", packet)
|
||||||
in_command_data_buf = self._get_packet_pre_alloc(datalen)
|
in_command_data_buf = self._get_packet_pre_alloc(datalen)
|
||||||
self.put_bytes(self.__out_command_header_ack, self._put_short_timeout)
|
self.put_bytes(self.__out_command_header_ack, self._put_short_timeout)
|
||||||
dat_packet = self._get_packet(self._COMMAND_DATA_PACKET_MAGIC, in_command_data_buf, self._get_long_timeout)
|
dat_packet = self._get_packet(
|
||||||
|
self._COMMAND_DATA_PACKET_MAGIC, in_command_data_buf, self._get_long_timeout
|
||||||
|
)
|
||||||
if dat_packet is not None:
|
if dat_packet is not None:
|
||||||
self.put_bytes(self.__out_command_data_ack, self._put_short_timeout)
|
self.put_bytes(self.__out_command_data_ack, self._put_short_timeout)
|
||||||
return (command, dat_packet)
|
return (command, dat_packet)
|
||||||
@ -245,7 +301,9 @@ class rpc_slave(rpc):
|
|||||||
def __put_result(self, data, timeout): # private
|
def __put_result(self, data, timeout): # private
|
||||||
self._put_short_timeout = self._put_short_timeout_reset
|
self._put_short_timeout = self._put_short_timeout_reset
|
||||||
self._get_short_timeout = self._get_short_timeout_reset
|
self._get_short_timeout = self._get_short_timeout_reset
|
||||||
out_header = self._set_packet(self._RESULT_HEADER_PACKET_MAGIC, struct.pack("<I", len(data)))
|
out_header = self._set_packet(
|
||||||
|
self._RESULT_HEADER_PACKET_MAGIC, struct.pack("<I", len(data))
|
||||||
|
)
|
||||||
out_data = self._set_packet(self._RESULT_DATA_PACKET_MAGIC, data)
|
out_data = self._set_packet(self._RESULT_DATA_PACKET_MAGIC, data)
|
||||||
start = pyb.millis()
|
start = pyb.millis()
|
||||||
while pyb.elapsed_millis(start) < timeout:
|
while pyb.elapsed_millis(start) < timeout:
|
||||||
@ -253,9 +311,23 @@ class rpc_slave(rpc):
|
|||||||
self._zero(self.__in_response_header_buf[0], len(self.__in_response_header_buf[0]))
|
self._zero(self.__in_response_header_buf[0], len(self.__in_response_header_buf[0]))
|
||||||
self._zero(self.__in_response_data_buf[0], len(self.__in_response_data_buf[0]))
|
self._zero(self.__in_response_data_buf[0], len(self.__in_response_data_buf[0]))
|
||||||
self._flush()
|
self._flush()
|
||||||
if self._get_packet(self._RESULT_HEADER_PACKET_MAGIC, self.__in_response_header_buf, self._get_short_timeout) is not None:
|
if (
|
||||||
|
self._get_packet(
|
||||||
|
self._RESULT_HEADER_PACKET_MAGIC,
|
||||||
|
self.__in_response_header_buf,
|
||||||
|
self._get_short_timeout,
|
||||||
|
)
|
||||||
|
is not None
|
||||||
|
):
|
||||||
self.put_bytes(out_header, self._put_short_timeout)
|
self.put_bytes(out_header, self._put_short_timeout)
|
||||||
if self._get_packet(self._RESULT_DATA_PACKET_MAGIC, self.__in_response_data_buf, self._get_short_timeout) is not None:
|
if (
|
||||||
|
self._get_packet(
|
||||||
|
self._RESULT_DATA_PACKET_MAGIC,
|
||||||
|
self.__in_response_data_buf,
|
||||||
|
self._get_short_timeout,
|
||||||
|
)
|
||||||
|
is not None
|
||||||
|
):
|
||||||
self.put_bytes(out_data, self._put_long_timeout)
|
self.put_bytes(out_data, self._put_long_timeout)
|
||||||
return True
|
return True
|
||||||
# Avoid timeout livelocking.
|
# Avoid timeout livelocking.
|
||||||
@ -277,21 +349,37 @@ class rpc_slave(rpc):
|
|||||||
command, data = self.__get_command(recv_timeout)
|
command, data = self.__get_command(recv_timeout)
|
||||||
if command is not None:
|
if command is not None:
|
||||||
cb = self.__dict.get(command)
|
cb = self.__dict.get(command)
|
||||||
if self.__put_result(cb(data) if cb is not None else bytes(), send_timeout) and self.__schedule_cb is not None:
|
if (
|
||||||
|
self.__put_result(cb(data) if cb is not None else bytes(), send_timeout)
|
||||||
|
and self.__schedule_cb is not None
|
||||||
|
):
|
||||||
self.__schedule_cb()
|
self.__schedule_cb()
|
||||||
self.__schedule_cb = None
|
self.__schedule_cb = None
|
||||||
if self.__loop_cb is not None: self.__loop_cb()
|
if self.__loop_cb is not None:
|
||||||
|
self.__loop_cb()
|
||||||
|
|
||||||
|
|
||||||
class rpc_can_master(rpc_master):
|
class rpc_can_master(rpc_master):
|
||||||
|
|
||||||
def __init__(self, message_id=0x7FF, bit_rate=250000, sample_point=75, can_bus=2):
|
def __init__(self, message_id=0x7FF, bit_rate=250000, sample_point=75, can_bus=2):
|
||||||
self.__message_id = message_id
|
self.__message_id = message_id
|
||||||
self.__can = pyb.CAN(can_bus, pyb.CAN.NORMAL, baudrate=bit_rate, sample_point=sample_point, auto_restart=True)
|
self.__can = pyb.CAN(
|
||||||
self.__can.setfilter(0, pyb.CAN.DUAL if omv.board_type() == "H7" else pyb.CAN.LIST32, 0, [message_id, message_id])
|
can_bus,
|
||||||
|
pyb.CAN.NORMAL,
|
||||||
|
baudrate=bit_rate,
|
||||||
|
sample_point=sample_point,
|
||||||
|
auto_restart=True,
|
||||||
|
)
|
||||||
|
self.__can.setfilter(
|
||||||
|
0,
|
||||||
|
pyb.CAN.DUAL if omv.board_type() == "H7" else pyb.CAN.LIST32,
|
||||||
|
0,
|
||||||
|
[message_id, message_id],
|
||||||
|
)
|
||||||
rpc_master.__init__(self)
|
rpc_master.__init__(self)
|
||||||
|
|
||||||
def _flush(self): # private
|
def _flush(self): # private
|
||||||
while self.__can.any(0): self.__can.recv(0)
|
while self.__can.any(0):
|
||||||
|
self.__can.recv(0)
|
||||||
|
|
||||||
def get_bytes(self, buff, timeout_ms): # protected
|
def get_bytes(self, buff, timeout_ms): # protected
|
||||||
msg = bytearray(8)
|
msg = bytearray(8)
|
||||||
@ -301,7 +389,8 @@ class rpc_can_master(rpc_master):
|
|||||||
expected = min(l - i, 8)
|
expected = min(l - i, 8)
|
||||||
try:
|
try:
|
||||||
id, rtr, fmi, data = self.__can.recv(0, lst, timeout=timeout_ms)
|
id, rtr, fmi, data = self.__can.recv(0, lst, timeout=timeout_ms)
|
||||||
if id == self.__message_id and rtr == 0 and fmi == 0 and len(data) == expected: buff[i:i+8] = data
|
if id == self.__message_id and rtr == 0 and fmi == 0 and len(data) == expected:
|
||||||
|
buff[i : i + 8] = data
|
||||||
else:
|
else:
|
||||||
pyb.delay(self._get_short_timeout)
|
pyb.delay(self._get_short_timeout)
|
||||||
return None
|
return None
|
||||||
@ -313,19 +402,33 @@ class rpc_can_master(rpc_master):
|
|||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
view = memoryview(data)
|
view = memoryview(data)
|
||||||
for i in range(0, len(view), 8):
|
for i in range(0, len(view), 8):
|
||||||
try: self.__can.send(view[i:i+8], self.__message_id, timeout=timeout_ms)
|
try:
|
||||||
except OSError: break
|
self.__can.send(view[i : i + 8], self.__message_id, timeout=timeout_ms)
|
||||||
|
except OSError:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
class rpc_can_slave(rpc_slave):
|
class rpc_can_slave(rpc_slave):
|
||||||
|
|
||||||
def __init__(self, message_id=0x7FF, bit_rate=250000, sample_point=75, can_bus=2):
|
def __init__(self, message_id=0x7FF, bit_rate=250000, sample_point=75, can_bus=2):
|
||||||
self.__message_id = message_id
|
self.__message_id = message_id
|
||||||
self.__can = pyb.CAN(can_bus, pyb.CAN.NORMAL, baudrate=bit_rate, sample_point=sample_point, auto_restart=True)
|
self.__can = pyb.CAN(
|
||||||
self.__can.setfilter(0, pyb.CAN.DUAL if omv.board_type() == "H7" else pyb.CAN.LIST32, 0, [message_id, message_id])
|
can_bus,
|
||||||
|
pyb.CAN.NORMAL,
|
||||||
|
baudrate=bit_rate,
|
||||||
|
sample_point=sample_point,
|
||||||
|
auto_restart=True,
|
||||||
|
)
|
||||||
|
self.__can.setfilter(
|
||||||
|
0,
|
||||||
|
pyb.CAN.DUAL if omv.board_type() == "H7" else pyb.CAN.LIST32,
|
||||||
|
0,
|
||||||
|
[message_id, message_id],
|
||||||
|
)
|
||||||
rpc_slave.__init__(self)
|
rpc_slave.__init__(self)
|
||||||
|
|
||||||
def _flush(self): # private
|
def _flush(self): # private
|
||||||
while self.__can.any(0): self.__can.recv(0)
|
while self.__can.any(0):
|
||||||
|
self.__can.recv(0)
|
||||||
|
|
||||||
def get_bytes(self, buff, timeout_ms): # protected
|
def get_bytes(self, buff, timeout_ms): # protected
|
||||||
msg = bytearray(8)
|
msg = bytearray(8)
|
||||||
@ -335,19 +438,24 @@ class rpc_can_slave(rpc_slave):
|
|||||||
expected = min(l - i, 8)
|
expected = min(l - i, 8)
|
||||||
try:
|
try:
|
||||||
id, rtr, fmi, data = self.__can.recv(0, lst, timeout=timeout_ms)
|
id, rtr, fmi, data = self.__can.recv(0, lst, timeout=timeout_ms)
|
||||||
if id == self.__message_id and rtr == 0 and fmi == 0 and len(data) == expected: buff[i:i+8] = data
|
if id == self.__message_id and rtr == 0 and fmi == 0 and len(data) == expected:
|
||||||
else: return None
|
buff[i : i + 8] = data
|
||||||
except OSError: return None
|
else:
|
||||||
|
return None
|
||||||
|
except OSError:
|
||||||
|
return None
|
||||||
return buff
|
return buff
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
view = memoryview(data)
|
view = memoryview(data)
|
||||||
for i in range(0, len(view), 8):
|
for i in range(0, len(view), 8):
|
||||||
try: self.__can.send(view[i:i+8], self.__message_id, timeout=timeout_ms)
|
try:
|
||||||
except OSError: break
|
self.__can.send(view[i : i + 8], self.__message_id, timeout=timeout_ms)
|
||||||
|
except OSError:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
class rpc_i2c_master(rpc_master):
|
class rpc_i2c_master(rpc_master):
|
||||||
|
|
||||||
def __init__(self, slave_addr=0x12, rate=100000, i2c_bus=2): # private
|
def __init__(self, slave_addr=0x12, rate=100000, i2c_bus=2): # private
|
||||||
self.__addr = slave_addr
|
self.__addr = slave_addr
|
||||||
self.__freq = rate
|
self.__freq = rate
|
||||||
@ -360,11 +468,15 @@ class rpc_i2c_master(rpc_master):
|
|||||||
for i in range(0, len(view), 65535):
|
for i in range(0, len(view), 65535):
|
||||||
pyb.udelay(100) # Give slave time to get ready.
|
pyb.udelay(100) # Give slave time to get ready.
|
||||||
self.__i2c.init(pyb.I2C.MASTER, baudrate=self.__freq, dma=True)
|
self.__i2c.init(pyb.I2C.MASTER, baudrate=self.__freq, dma=True)
|
||||||
try: self.__i2c.recv(view[i:i+65535], self.__addr, timeout=timeout_ms)
|
try:
|
||||||
except OSError: view = None
|
self.__i2c.recv(view[i : i + 65535], self.__addr, timeout=timeout_ms)
|
||||||
|
except OSError:
|
||||||
|
view = None
|
||||||
self.__i2c.deinit()
|
self.__i2c.deinit()
|
||||||
if view is None: break
|
if view is None:
|
||||||
if view is None or self._same(view, len(view)): pyb.delay(self._get_short_timeout)
|
break
|
||||||
|
if view is None or self._same(view, len(view)):
|
||||||
|
pyb.delay(self._get_short_timeout)
|
||||||
return view
|
return view
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
@ -372,13 +484,16 @@ class rpc_i2c_master(rpc_master):
|
|||||||
for i in range(0, len(view), 65535):
|
for i in range(0, len(view), 65535):
|
||||||
pyb.udelay(100) # Give slave time to get ready.
|
pyb.udelay(100) # Give slave time to get ready.
|
||||||
self.__i2c.init(pyb.I2C.MASTER, baudrate=self.__freq, dma=True)
|
self.__i2c.init(pyb.I2C.MASTER, baudrate=self.__freq, dma=True)
|
||||||
try: self.__i2c.send(view[i:i+65535], self.__addr, timeout=timeout_ms)
|
try:
|
||||||
except OSError: view = None
|
self.__i2c.send(view[i : i + 65535], self.__addr, timeout=timeout_ms)
|
||||||
|
except OSError:
|
||||||
|
view = None
|
||||||
self.__i2c.deinit()
|
self.__i2c.deinit()
|
||||||
if view is None: break
|
if view is None:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
class rpc_i2c_slave(rpc_slave):
|
class rpc_i2c_slave(rpc_slave):
|
||||||
|
|
||||||
def __init__(self, slave_addr=0x12, i2c_bus=2): # private
|
def __init__(self, slave_addr=0x12, i2c_bus=2): # private
|
||||||
self.__addr = slave_addr
|
self.__addr = slave_addr
|
||||||
self.__i2c = pyb.I2C(i2c_bus)
|
self.__i2c = pyb.I2C(i2c_bus)
|
||||||
@ -389,24 +504,32 @@ class rpc_i2c_slave(rpc_slave):
|
|||||||
view = memoryview(buff)
|
view = memoryview(buff)
|
||||||
for i in range(0, len(view), 65535):
|
for i in range(0, len(view), 65535):
|
||||||
self.__i2c.init(pyb.I2C.SLAVE, addr=self.__addr, dma=True)
|
self.__i2c.init(pyb.I2C.SLAVE, addr=self.__addr, dma=True)
|
||||||
try: self.__i2c.recv(view[i:i+65535], timeout=timeout_ms)
|
try:
|
||||||
except OSError: view = None
|
self.__i2c.recv(view[i : i + 65535], timeout=timeout_ms)
|
||||||
|
except OSError:
|
||||||
|
view = None
|
||||||
self.__i2c.deinit()
|
self.__i2c.deinit()
|
||||||
if view is None: break
|
if view is None:
|
||||||
|
break
|
||||||
return view
|
return view
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
view = memoryview(data)
|
view = memoryview(data)
|
||||||
for i in range(0, len(view), 65535):
|
for i in range(0, len(view), 65535):
|
||||||
self.__i2c.init(pyb.I2C.SLAVE, addr=self.__addr, dma=True)
|
self.__i2c.init(pyb.I2C.SLAVE, addr=self.__addr, dma=True)
|
||||||
try: self.__i2c.send(view[i:i+65535], timeout=timeout_ms)
|
try:
|
||||||
except OSError: view = None
|
self.__i2c.send(view[i : i + 65535], timeout=timeout_ms)
|
||||||
|
except OSError:
|
||||||
|
view = None
|
||||||
self.__i2c.deinit()
|
self.__i2c.deinit()
|
||||||
if view is None: break
|
if view is None:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
class rpc_spi_master(rpc_master):
|
class rpc_spi_master(rpc_master):
|
||||||
|
def __init__(
|
||||||
def __init__(self, cs_pin="P3", freq=1000000, clk_polarity=1, clk_phase=0, spi_bus=2): # private
|
self, cs_pin="P3", freq=1000000, clk_polarity=1, clk_phase=0, spi_bus=2
|
||||||
|
): # private
|
||||||
self.__pin = pyb.Pin(cs_pin, pyb.Pin.OUT_PP)
|
self.__pin = pyb.Pin(cs_pin, pyb.Pin.OUT_PP)
|
||||||
self.__freq = freq
|
self.__freq = freq
|
||||||
self.__polarity = clk_polarity
|
self.__polarity = clk_polarity
|
||||||
@ -418,25 +541,34 @@ class rpc_spi_master(rpc_master):
|
|||||||
def get_bytes(self, buff, timeout_ms): # protected
|
def get_bytes(self, buff, timeout_ms): # protected
|
||||||
self.__pin.value(False)
|
self.__pin.value(False)
|
||||||
pyb.udelay(100) # Give slave time to get ready.
|
pyb.udelay(100) # Give slave time to get ready.
|
||||||
self.__spi.init(pyb.SPI.MASTER, self.__freq, polarity=self.__polarity, phase=self.__clk_phase)
|
self.__spi.init(
|
||||||
try: self.__spi.send_recv(buff, buff, timeout=timeout_ms) # SPI.recv() is broken.
|
pyb.SPI.MASTER, self.__freq, polarity=self.__polarity, phase=self.__clk_phase
|
||||||
except OSError: buff = None
|
)
|
||||||
|
try:
|
||||||
|
self.__spi.send_recv(buff, buff, timeout=timeout_ms) # SPI.recv() is broken.
|
||||||
|
except OSError:
|
||||||
|
buff = None
|
||||||
self.__spi.deinit()
|
self.__spi.deinit()
|
||||||
self.__pin.value(True)
|
self.__pin.value(True)
|
||||||
if buff is None or self._same(buff, len(buff)): pyb.delay(self._get_short_timeout)
|
if buff is None or self._same(buff, len(buff)):
|
||||||
|
pyb.delay(self._get_short_timeout)
|
||||||
return buff
|
return buff
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
self.__pin.value(False)
|
self.__pin.value(False)
|
||||||
pyb.udelay(100) # Give slave time to get ready.
|
pyb.udelay(100) # Give slave time to get ready.
|
||||||
self.__spi.init(pyb.SPI.MASTER, self.__freq, polarity=self.__polarity, phase=self.__clk_phase)
|
self.__spi.init(
|
||||||
try: self.__spi.send(data, timeout=timeout_ms)
|
pyb.SPI.MASTER, self.__freq, polarity=self.__polarity, phase=self.__clk_phase
|
||||||
except OSError: pass
|
)
|
||||||
|
try:
|
||||||
|
self.__spi.send(data, timeout=timeout_ms)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
self.__spi.deinit()
|
self.__spi.deinit()
|
||||||
self.__pin.value(True)
|
self.__pin.value(True)
|
||||||
|
|
||||||
class rpc_spi_slave(rpc_slave):
|
|
||||||
|
|
||||||
|
class rpc_spi_slave(rpc_slave):
|
||||||
def __init__(self, cs_pin="P3", clk_polarity=1, clk_phase=0, spi_bus=2): # private
|
def __init__(self, cs_pin="P3", clk_polarity=1, clk_phase=0, spi_bus=2): # private
|
||||||
self.__pin = pyb.Pin(cs_pin, pyb.Pin.IN)
|
self.__pin = pyb.Pin(cs_pin, pyb.Pin.IN)
|
||||||
self.__polarity = clk_polarity
|
self.__polarity = clk_polarity
|
||||||
@ -447,25 +579,31 @@ class rpc_spi_slave(rpc_slave):
|
|||||||
|
|
||||||
def get_bytes(self, buff, timeout_ms): # protected
|
def get_bytes(self, buff, timeout_ms): # protected
|
||||||
start = pyb.millis()
|
start = pyb.millis()
|
||||||
while(self.__pin.value()):
|
while self.__pin.value():
|
||||||
if pyb.elapsed_millis(start) >= self._get_short_timeout: return None
|
if pyb.elapsed_millis(start) >= self._get_short_timeout:
|
||||||
|
return None
|
||||||
self.__spi.init(pyb.SPI.SLAVE, polarity=self.__polarity, phase=self.__clk_phase)
|
self.__spi.init(pyb.SPI.SLAVE, polarity=self.__polarity, phase=self.__clk_phase)
|
||||||
try: self.__spi.send_recv(buff, buff, timeout=timeout_ms) # SPI.recv() is broken.
|
try:
|
||||||
except OSError: buff = None
|
self.__spi.send_recv(buff, buff, timeout=timeout_ms) # SPI.recv() is broken.
|
||||||
|
except OSError:
|
||||||
|
buff = None
|
||||||
self.__spi.deinit()
|
self.__spi.deinit()
|
||||||
return buff
|
return buff
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
start = pyb.millis()
|
start = pyb.millis()
|
||||||
while(self.__pin.value()):
|
while self.__pin.value():
|
||||||
if pyb.elapsed_millis(start) >= self._put_short_timeout: return
|
if pyb.elapsed_millis(start) >= self._put_short_timeout:
|
||||||
|
return
|
||||||
self.__spi.init(pyb.SPI.SLAVE, polarity=self.__polarity, phase=self.__clk_phase)
|
self.__spi.init(pyb.SPI.SLAVE, polarity=self.__polarity, phase=self.__clk_phase)
|
||||||
try: self.__spi.send(data, timeout=timeout_ms)
|
try:
|
||||||
except OSError: pass
|
self.__spi.send(data, timeout=timeout_ms)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
self.__spi.deinit()
|
self.__spi.deinit()
|
||||||
|
|
||||||
class rpc_uart_master(rpc_master):
|
|
||||||
|
|
||||||
|
class rpc_uart_master(rpc_master):
|
||||||
def __init__(self, baudrate=9600, uart_port=3): # private
|
def __init__(self, baudrate=9600, uart_port=3): # private
|
||||||
self.__uart = pyb.UART(uart_port, baudrate, timeout=2, timeout_char=2)
|
self.__uart = pyb.UART(uart_port, baudrate, timeout=2, timeout_char=2)
|
||||||
rpc_master.__init__(self)
|
rpc_master.__init__(self)
|
||||||
@ -488,8 +626,8 @@ class rpc_uart_master(rpc_master):
|
|||||||
p.poll(1000)
|
p.poll(1000)
|
||||||
return self.get_bytes(buff, timeout_ms)
|
return self.get_bytes(buff, timeout_ms)
|
||||||
|
|
||||||
class rpc_uart_slave(rpc_slave):
|
|
||||||
|
|
||||||
|
class rpc_uart_slave(rpc_slave):
|
||||||
def __init__(self, baudrate=9600, uart_port=3): # private
|
def __init__(self, baudrate=9600, uart_port=3): # private
|
||||||
self.__uart = pyb.UART(uart_port, baudrate, timeout=2, timeout_char=2)
|
self.__uart = pyb.UART(uart_port, baudrate, timeout=2, timeout_char=2)
|
||||||
rpc_slave.__init__(self)
|
rpc_slave.__init__(self)
|
||||||
@ -498,7 +636,8 @@ class rpc_uart_slave(rpc_slave):
|
|||||||
self.__uart.read(self.__uart.any())
|
self.__uart.read(self.__uart.any())
|
||||||
|
|
||||||
def get_bytes(self, buff, timeout_ms): # protected
|
def get_bytes(self, buff, timeout_ms): # protected
|
||||||
if self.__uart.readinto(buff) is None: return None
|
if self.__uart.readinto(buff) is None:
|
||||||
|
return None
|
||||||
return buff
|
return buff
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
@ -510,11 +649,12 @@ class rpc_uart_slave(rpc_slave):
|
|||||||
p.poll(1000)
|
p.poll(1000)
|
||||||
return self.get_bytes(buff, timeout_ms)
|
return self.get_bytes(buff, timeout_ms)
|
||||||
|
|
||||||
class rpc_usb_vcp_master(rpc_master):
|
|
||||||
|
|
||||||
|
class rpc_usb_vcp_master(rpc_master):
|
||||||
def __init__(self): # private
|
def __init__(self): # private
|
||||||
self.__usb_vcp = pyb.USB_VCP()
|
self.__usb_vcp = pyb.USB_VCP()
|
||||||
if self.__usb_vcp.debug_mode_enabled(): raise OSError("You cannot use the USB VCP while the IDE is connected!")
|
if self.__usb_vcp.debug_mode_enabled():
|
||||||
|
raise OSError("You cannot use the USB VCP while the IDE is connected!")
|
||||||
self.__usb_vcp.setinterrupt(-1)
|
self.__usb_vcp.setinterrupt(-1)
|
||||||
rpc_master.__init__(self)
|
rpc_master.__init__(self)
|
||||||
|
|
||||||
@ -522,17 +662,19 @@ class rpc_usb_vcp_master(rpc_master):
|
|||||||
self.__usb_vcp.read()
|
self.__usb_vcp.read()
|
||||||
|
|
||||||
def get_bytes(self, buff, timeout_ms): # protected
|
def get_bytes(self, buff, timeout_ms): # protected
|
||||||
if self.__usb_vcp.recv(buff, timeout=timeout_ms) != len(buff): return None
|
if self.__usb_vcp.recv(buff, timeout=timeout_ms) != len(buff):
|
||||||
|
return None
|
||||||
return buff
|
return buff
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
self.__usb_vcp.send(data, timeout=timeout_ms)
|
self.__usb_vcp.send(data, timeout=timeout_ms)
|
||||||
|
|
||||||
class rpc_usb_vcp_slave(rpc_slave):
|
|
||||||
|
|
||||||
|
class rpc_usb_vcp_slave(rpc_slave):
|
||||||
def __init__(self): # private
|
def __init__(self): # private
|
||||||
self.__usb_vcp = pyb.USB_VCP()
|
self.__usb_vcp = pyb.USB_VCP()
|
||||||
if self.__usb_vcp.debug_mode_enabled(): raise OSError("You cannot use the USB VCP while the IDE is connected!")
|
if self.__usb_vcp.debug_mode_enabled():
|
||||||
|
raise OSError("You cannot use the USB VCP while the IDE is connected!")
|
||||||
self.__usb_vcp.setinterrupt(-1)
|
self.__usb_vcp.setinterrupt(-1)
|
||||||
rpc_slave.__init__(self)
|
rpc_slave.__init__(self)
|
||||||
|
|
||||||
@ -540,14 +682,15 @@ class rpc_usb_vcp_slave(rpc_slave):
|
|||||||
self.__usb_vcp.read()
|
self.__usb_vcp.read()
|
||||||
|
|
||||||
def get_bytes(self, buff, timeout_ms): # protected
|
def get_bytes(self, buff, timeout_ms): # protected
|
||||||
if self.__usb_vcp.recv(buff, timeout=timeout_ms) != len(buff): return None
|
if self.__usb_vcp.recv(buff, timeout=timeout_ms) != len(buff):
|
||||||
|
return None
|
||||||
return buff
|
return buff
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
self.__usb_vcp.send(data, timeout=timeout_ms)
|
self.__usb_vcp.send(data, timeout=timeout_ms)
|
||||||
|
|
||||||
class rpc_network_master(rpc_master):
|
|
||||||
|
|
||||||
|
class rpc_network_master(rpc_master):
|
||||||
def __valid_tcp_socket(self): # private
|
def __valid_tcp_socket(self): # private
|
||||||
if self.__tcp__socket is None:
|
if self.__tcp__socket is None:
|
||||||
try:
|
try:
|
||||||
@ -557,7 +700,8 @@ class rpc_network_master(rpc_master):
|
|||||||
s.settimeout(1)
|
s.settimeout(1)
|
||||||
self.__tcp__socket, addr = s.accept()
|
self.__tcp__socket, addr = s.accept()
|
||||||
s.close()
|
s.close()
|
||||||
except OSError: self.__tcp__socket = None
|
except OSError:
|
||||||
|
self.__tcp__socket = None
|
||||||
return self.__tcp__socket is not None
|
return self.__tcp__socket is not None
|
||||||
|
|
||||||
def __close_tcp_socket(self): # private
|
def __close_tcp_socket(self): # private
|
||||||
@ -569,7 +713,8 @@ class rpc_network_master(rpc_master):
|
|||||||
try:
|
try:
|
||||||
self.__udp__socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
self.__udp__socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
self.__udp__socket.bind(self.__myaddr)
|
self.__udp__socket.bind(self.__myaddr)
|
||||||
except OSError: self.__udp__socket = None
|
except OSError:
|
||||||
|
self.__udp__socket = None
|
||||||
return self.__udp__socket is not None
|
return self.__udp__socket is not None
|
||||||
|
|
||||||
def __close_udp_socket(self): # private
|
def __close_udp_socket(self): # private
|
||||||
@ -592,17 +737,21 @@ class rpc_network_master(rpc_master):
|
|||||||
if self.__valid_udp_socket():
|
if self.__valid_udp_socket():
|
||||||
try:
|
try:
|
||||||
self.__udp__socket.settimeout(0.001)
|
self.__udp__socket.settimeout(0.001)
|
||||||
while(True):
|
while True:
|
||||||
data, addr = self.__udp__socket.recvfrom(1400)
|
data, addr = self.__udp__socket.recvfrom(1400)
|
||||||
if not len(data): break
|
if not len(data):
|
||||||
except OSError: self.__close_udp_socket()
|
break
|
||||||
|
except OSError:
|
||||||
|
self.__close_udp_socket()
|
||||||
if self.__tcp__socket is not None:
|
if self.__tcp__socket is not None:
|
||||||
try:
|
try:
|
||||||
self.__tcp__socket.settimeout(0.001)
|
self.__tcp__socket.settimeout(0.001)
|
||||||
while(True):
|
while True:
|
||||||
data = self.__tcp__socket.recv(1400)
|
data = self.__tcp__socket.recv(1400)
|
||||||
if not len(data): break
|
if not len(data):
|
||||||
except OSError: self.__close_tcp_socket()
|
break
|
||||||
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
|
|
||||||
def get_bytes(self, buff, timeout_ms): # protected
|
def get_bytes(self, buff, timeout_ms): # protected
|
||||||
i = 0
|
i = 0
|
||||||
@ -610,28 +759,35 @@ class rpc_network_master(rpc_master):
|
|||||||
if l <= self._udp_limit:
|
if l <= self._udp_limit:
|
||||||
if self.__valid_udp_socket():
|
if self.__valid_udp_socket():
|
||||||
try:
|
try:
|
||||||
self.__udp__socket.settimeout(self._get_short_timeout * 0.001 * self._timeout_scale)
|
self.__udp__socket.settimeout(
|
||||||
|
self._get_short_timeout * 0.001 * self._timeout_scale
|
||||||
|
)
|
||||||
while l:
|
while l:
|
||||||
data, addr = self.__udp__socket.recvfrom(min(l, 1400))
|
data, addr = self.__udp__socket.recvfrom(min(l, 1400))
|
||||||
data_len = len(data)
|
data_len = len(data)
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
buff[i : i + data_len] = data
|
buff[i : i + data_len] = data
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
# We don't need to close the socket on error since it's connectionless.
|
# We don't need to close the socket on error since it's connectionless.
|
||||||
except OSError: self.__close_udp_socket()
|
except OSError:
|
||||||
|
self.__close_udp_socket()
|
||||||
elif self.__valid_tcp_socket():
|
elif self.__valid_tcp_socket():
|
||||||
try:
|
try:
|
||||||
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
||||||
while l:
|
while l:
|
||||||
data = self.__tcp__socket.recv(min(l, 1400))
|
data = self.__tcp__socket.recv(min(l, 1400))
|
||||||
data_len = len(data)
|
data_len = len(data)
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
buff[i : i + data_len] = data
|
buff[i : i + data_len] = data
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_tcp_socket()
|
if l:
|
||||||
except OSError: self.__close_tcp_socket()
|
self.__close_tcp_socket()
|
||||||
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
return buff if not l else None
|
return buff if not l else None
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
@ -640,24 +796,34 @@ class rpc_network_master(rpc_master):
|
|||||||
if l <= self._udp_limit:
|
if l <= self._udp_limit:
|
||||||
if self.__valid_udp_socket():
|
if self.__valid_udp_socket():
|
||||||
try:
|
try:
|
||||||
self.__udp__socket.settimeout(self._put_short_timeout * 0.001 * self._timeout_scale)
|
self.__udp__socket.settimeout(
|
||||||
|
self._put_short_timeout * 0.001 * self._timeout_scale
|
||||||
|
)
|
||||||
while l:
|
while l:
|
||||||
data_len = self.__udp__socket.sendto(data[i:i+min(l, 1400)], self.__slave_addr)
|
data_len = self.__udp__socket.sendto(
|
||||||
if not data_len: break
|
data[i : i + min(l, 1400)], self.__slave_addr
|
||||||
|
)
|
||||||
|
if not data_len:
|
||||||
|
break
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_udp_socket()
|
if l:
|
||||||
except OSError: self.__close_udp_socket()
|
self.__close_udp_socket()
|
||||||
|
except OSError:
|
||||||
|
self.__close_udp_socket()
|
||||||
elif self.__valid_tcp_socket():
|
elif self.__valid_tcp_socket():
|
||||||
try:
|
try:
|
||||||
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
||||||
while l:
|
while l:
|
||||||
data_len = self.__tcp__socket.send(data[i : i + min(l, 1400)])
|
data_len = self.__tcp__socket.send(data[i : i + min(l, 1400)])
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_tcp_socket()
|
if l:
|
||||||
except OSError: self.__close_tcp_socket()
|
self.__close_tcp_socket()
|
||||||
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
|
|
||||||
def _stream_get_bytes(self, buff, timeout_ms): # protected
|
def _stream_get_bytes(self, buff, timeout_ms): # protected
|
||||||
i = 0
|
i = 0
|
||||||
@ -668,12 +834,15 @@ class rpc_network_master(rpc_master):
|
|||||||
while l:
|
while l:
|
||||||
data = self.__tcp__socket.recv(min(l, 1400))
|
data = self.__tcp__socket.recv(min(l, 1400))
|
||||||
data_len = len(data)
|
data_len = len(data)
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
buff[i : i + data_len] = data
|
buff[i : i + data_len] = data
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_tcp_socket()
|
if l:
|
||||||
except OSError: self.__close_tcp_socket()
|
self.__close_tcp_socket()
|
||||||
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
return buff if not l else None
|
return buff if not l else None
|
||||||
|
|
||||||
def _stream_put_bytes(self, data, timeout_ms): # protected
|
def _stream_put_bytes(self, data, timeout_ms): # protected
|
||||||
@ -684,21 +853,26 @@ class rpc_network_master(rpc_master):
|
|||||||
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
||||||
while l:
|
while l:
|
||||||
data_len = self.__tcp__socket.send(data[i : i + min(l, 1400)])
|
data_len = self.__tcp__socket.send(data[i : i + min(l, 1400)])
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_tcp_socket()
|
if l:
|
||||||
except OSError: self.__close_tcp_socket()
|
self.__close_tcp_socket()
|
||||||
if l: raise OSError # Stop Stream.
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
|
if l:
|
||||||
|
raise OSError # Stop Stream.
|
||||||
|
|
||||||
|
|
||||||
class rpc_network_slave(rpc_slave):
|
class rpc_network_slave(rpc_slave):
|
||||||
|
|
||||||
def __valid_tcp_socket(self): # private
|
def __valid_tcp_socket(self): # private
|
||||||
if self.__tcp__socket is None:
|
if self.__tcp__socket is None:
|
||||||
try:
|
try:
|
||||||
self.__tcp__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.__tcp__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.__tcp__socket.connect(self.__master_addr)
|
self.__tcp__socket.connect(self.__master_addr)
|
||||||
except OSError: self.__tcp__socket = None
|
except OSError:
|
||||||
|
self.__tcp__socket = None
|
||||||
return self.__tcp__socket is not None
|
return self.__tcp__socket is not None
|
||||||
|
|
||||||
def __close_tcp_socket(self): # private
|
def __close_tcp_socket(self): # private
|
||||||
@ -710,7 +884,8 @@ class rpc_network_slave(rpc_slave):
|
|||||||
try:
|
try:
|
||||||
self.__udp__socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
self.__udp__socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
self.__udp__socket.bind(self.__myaddr)
|
self.__udp__socket.bind(self.__myaddr)
|
||||||
except OSError: self.__udp__socket = None
|
except OSError:
|
||||||
|
self.__udp__socket = None
|
||||||
return self.__udp__socket is not None
|
return self.__udp__socket is not None
|
||||||
|
|
||||||
def __close_udp_socket(self): # private
|
def __close_udp_socket(self): # private
|
||||||
@ -733,17 +908,21 @@ class rpc_network_slave(rpc_slave):
|
|||||||
if self.__valid_udp_socket():
|
if self.__valid_udp_socket():
|
||||||
try:
|
try:
|
||||||
self.__udp__socket.settimeout(0.001)
|
self.__udp__socket.settimeout(0.001)
|
||||||
while(True):
|
while True:
|
||||||
data, addr = self.__udp__socket.recvfrom(1400)
|
data, addr = self.__udp__socket.recvfrom(1400)
|
||||||
if not len(data): break
|
if not len(data):
|
||||||
except OSError: self.__close_udp_socket()
|
break
|
||||||
|
except OSError:
|
||||||
|
self.__close_udp_socket()
|
||||||
if self.__tcp__socket is not None:
|
if self.__tcp__socket is not None:
|
||||||
try:
|
try:
|
||||||
self.__tcp__socket.settimeout(0.001)
|
self.__tcp__socket.settimeout(0.001)
|
||||||
while(True):
|
while True:
|
||||||
data = self.__tcp__socket.recv(1400)
|
data = self.__tcp__socket.recv(1400)
|
||||||
if not len(data): break
|
if not len(data):
|
||||||
except OSError: self.__close_tcp_socket()
|
break
|
||||||
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
|
|
||||||
def get_bytes(self, buff, timeout_ms): # protected
|
def get_bytes(self, buff, timeout_ms): # protected
|
||||||
i = 0
|
i = 0
|
||||||
@ -751,29 +930,36 @@ class rpc_network_slave(rpc_slave):
|
|||||||
if l <= self._udp_limit:
|
if l <= self._udp_limit:
|
||||||
if self.__valid_udp_socket():
|
if self.__valid_udp_socket():
|
||||||
try:
|
try:
|
||||||
self.__udp__socket.settimeout(self._get_short_timeout * 0.001 * self._timeout_scale)
|
self.__udp__socket.settimeout(
|
||||||
|
self._get_short_timeout * 0.001 * self._timeout_scale
|
||||||
|
)
|
||||||
while l:
|
while l:
|
||||||
data, addr = self.__udp__socket.recvfrom(min(l, 1400))
|
data, addr = self.__udp__socket.recvfrom(min(l, 1400))
|
||||||
data_len = len(data)
|
data_len = len(data)
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
buff[i : i + data_len] = data
|
buff[i : i + data_len] = data
|
||||||
self.__master_addr = addr
|
self.__master_addr = addr
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
# We don't need to close the socket on error since it's connectionless.
|
# We don't need to close the socket on error since it's connectionless.
|
||||||
except OSError: self.__close_udp_socket()
|
except OSError:
|
||||||
|
self.__close_udp_socket()
|
||||||
elif self.__valid_tcp_socket():
|
elif self.__valid_tcp_socket():
|
||||||
try:
|
try:
|
||||||
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
||||||
while l:
|
while l:
|
||||||
data = self.__tcp__socket.recv(min(l, 1400))
|
data = self.__tcp__socket.recv(min(l, 1400))
|
||||||
data_len = len(data)
|
data_len = len(data)
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
buff[i : i + data_len] = data
|
buff[i : i + data_len] = data
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_tcp_socket()
|
if l:
|
||||||
except OSError: self.__close_tcp_socket()
|
self.__close_tcp_socket()
|
||||||
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
return buff if not l else None
|
return buff if not l else None
|
||||||
|
|
||||||
def put_bytes(self, data, timeout_ms): # protected
|
def put_bytes(self, data, timeout_ms): # protected
|
||||||
@ -782,24 +968,34 @@ class rpc_network_slave(rpc_slave):
|
|||||||
if l <= self._udp_limit:
|
if l <= self._udp_limit:
|
||||||
if self.__valid_udp_socket():
|
if self.__valid_udp_socket():
|
||||||
try:
|
try:
|
||||||
self.__udp__socket.settimeout(self._put_short_timeout * 0.001 * self._timeout_scale)
|
self.__udp__socket.settimeout(
|
||||||
|
self._put_short_timeout * 0.001 * self._timeout_scale
|
||||||
|
)
|
||||||
while l:
|
while l:
|
||||||
data_len = self.__udp__socket.sendto(data[i:i+min(l, 1400)], self.__master_addr)
|
data_len = self.__udp__socket.sendto(
|
||||||
if not data_len: break
|
data[i : i + min(l, 1400)], self.__master_addr
|
||||||
|
)
|
||||||
|
if not data_len:
|
||||||
|
break
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_udp_socket()
|
if l:
|
||||||
except OSError: self.__close_udp_socket()
|
self.__close_udp_socket()
|
||||||
|
except OSError:
|
||||||
|
self.__close_udp_socket()
|
||||||
elif self.__valid_tcp_socket():
|
elif self.__valid_tcp_socket():
|
||||||
try:
|
try:
|
||||||
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
||||||
while l:
|
while l:
|
||||||
data_len = self.__tcp__socket.send(data[i : i + min(l, 1400)])
|
data_len = self.__tcp__socket.send(data[i : i + min(l, 1400)])
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_tcp_socket()
|
if l:
|
||||||
except OSError: self.__close_tcp_socket()
|
self.__close_tcp_socket()
|
||||||
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
|
|
||||||
def _stream_get_bytes(self, buff, timeout_ms): # protected
|
def _stream_get_bytes(self, buff, timeout_ms): # protected
|
||||||
i = 0
|
i = 0
|
||||||
@ -810,12 +1006,15 @@ class rpc_network_slave(rpc_slave):
|
|||||||
while l:
|
while l:
|
||||||
data = self.__tcp__socket.recv(min(l, 1400))
|
data = self.__tcp__socket.recv(min(l, 1400))
|
||||||
data_len = len(data)
|
data_len = len(data)
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
buff[i : i + data_len] = data
|
buff[i : i + data_len] = data
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_tcp_socket()
|
if l:
|
||||||
except OSError: self.__close_tcp_socket()
|
self.__close_tcp_socket()
|
||||||
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
return buff if not l else None
|
return buff if not l else None
|
||||||
|
|
||||||
def _stream_put_bytes(self, data, timeout_ms): # protected
|
def _stream_put_bytes(self, data, timeout_ms): # protected
|
||||||
@ -826,9 +1025,13 @@ class rpc_network_slave(rpc_slave):
|
|||||||
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
self.__tcp__socket.settimeout(timeout_ms * 0.001)
|
||||||
while l:
|
while l:
|
||||||
data_len = self.__tcp__socket.send(data[i : i + min(l, 1400)])
|
data_len = self.__tcp__socket.send(data[i : i + min(l, 1400)])
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
i += data_len
|
i += data_len
|
||||||
l -= data_len
|
l -= data_len
|
||||||
if l: self.__close_tcp_socket()
|
if l:
|
||||||
except OSError: self.__close_tcp_socket()
|
self.__close_tcp_socket()
|
||||||
if l: raise OSError # Stop Stream.
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
|
if l:
|
||||||
|
raise OSError # Stop Stream.
|
||||||
|
|||||||
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
import network, pyb, re, socket, struct
|
import network, pyb, re, socket, struct
|
||||||
|
|
||||||
class rtsp_server:
|
|
||||||
|
|
||||||
|
class rtsp_server:
|
||||||
def __valid_tcp_socket(self): # private
|
def __valid_tcp_socket(self): # private
|
||||||
if self.__tcp__socket is None:
|
if self.__tcp__socket is None:
|
||||||
try:
|
try:
|
||||||
@ -18,7 +18,8 @@ class rtsp_server:
|
|||||||
s.settimeout(5)
|
s.settimeout(5)
|
||||||
self.__tcp__socket, self.__client_addr = s.accept()
|
self.__tcp__socket, self.__client_addr = s.accept()
|
||||||
s.close()
|
s.close()
|
||||||
except OSError: self.__tcp__socket = None
|
except OSError:
|
||||||
|
self.__tcp__socket = None
|
||||||
return self.__tcp__socket is not None
|
return self.__tcp__socket is not None
|
||||||
|
|
||||||
def __close_tcp_socket(self): # private
|
def __close_tcp_socket(self): # private
|
||||||
@ -30,7 +31,8 @@ class rtsp_server:
|
|||||||
try:
|
try:
|
||||||
self.__udp__socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
self.__udp__socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
self.__udp__socket.bind((self.__myip, self.__client_rtp_port))
|
self.__udp__socket.bind((self.__myip, self.__client_rtp_port))
|
||||||
except OSError: self.__udp__socket = None
|
except OSError:
|
||||||
|
self.__udp__socket = None
|
||||||
return self.__udp__socket is not None
|
return self.__udp__socket is not None
|
||||||
|
|
||||||
def __close_udp_socket(self): # private
|
def __close_udp_socket(self): # private
|
||||||
@ -78,61 +80,103 @@ class rtsp_server:
|
|||||||
self.__send_rtsp_response_cseq(200, "OK", seq, extra)
|
self.__send_rtsp_response_cseq(200, "OK", seq, extra)
|
||||||
|
|
||||||
def __parse_rtsp_request(self, data): # private
|
def __parse_rtsp_request(self, data): # private
|
||||||
if data[0] == 0x24: return # Interleaved RTCP Packet
|
if data[0] == 0x24:
|
||||||
if data[0] >= 0x80: return # Ressambled TCP
|
return # Interleaved RTCP Packet
|
||||||
s = list(filter(lambda x: x and not x.startswith("User-Agent"), data.decode().splitlines()))
|
if data[0] >= 0x80:
|
||||||
|
return # Ressambled TCP
|
||||||
|
s = list(
|
||||||
|
filter(lambda x: x and not x.startswith("User-Agent"), data.decode().splitlines())
|
||||||
|
)
|
||||||
if s and len(s) >= 2:
|
if s and len(s) >= 2:
|
||||||
line0 = s[0].split(' ')
|
line0 = s[0].split(" ")
|
||||||
request = line0[0]
|
request = line0[0]
|
||||||
self.__pathname = re.sub("rtsp(u)?://[a-zA-Z0-9\-\.]+(:\d+)?(/)?", '/', line0[1])
|
self.__pathname = re.sub("rtsp(u)?://[a-zA-Z0-9\-\.]+(:\d+)?(/)?", "/", line0[1])
|
||||||
if self.__pathname != '/' and self.__pathname.endswith('/'):
|
if self.__pathname != "/" and self.__pathname.endswith("/"):
|
||||||
self.__pathname = self.__pathname[:-1]
|
self.__pathname = self.__pathname[:-1]
|
||||||
if line0[2] == "RTSP/1.0":
|
if line0[2] == "RTSP/1.0":
|
||||||
if len(s) >= 3 and s[1].split(' ')[0] != "CSeq:":
|
if len(s) >= 3 and s[1].split(" ")[0] != "CSeq:":
|
||||||
for i in range(2, len(s)):
|
for i in range(2, len(s)):
|
||||||
if s[i].split(' ')[0] == "CSeq:":
|
if s[i].split(" ")[0] == "CSeq:":
|
||||||
temp = s[i]
|
temp = s[i]
|
||||||
s[i] = s[1]
|
s[i] = s[1]
|
||||||
s[1] = temp
|
s[1] = temp
|
||||||
break
|
break
|
||||||
line1 = s[1].split(' ')
|
line1 = s[1].split(" ")
|
||||||
if line1[0] == "CSeq:":
|
if line1[0] == "CSeq:":
|
||||||
seq = int(line1[1])
|
seq = int(line1[1])
|
||||||
if request == "OPTIONS":
|
if request == "OPTIONS":
|
||||||
if len(s) >= 3:
|
if len(s) >= 3:
|
||||||
m = re.match("(Proxy-)?Require: (\S)+", s[2])
|
m = re.match("(Proxy-)?Require: (\S)+", s[2])
|
||||||
if m:
|
if m:
|
||||||
self.__send_rtsp_response_cseq(551, "Option not supported", seq, "Unsupported: %s\r\n" % m.group(2))
|
self.__send_rtsp_response_cseq(
|
||||||
|
551,
|
||||||
|
"Option not supported",
|
||||||
|
seq,
|
||||||
|
"Unsupported: %s\r\n" % m.group(2),
|
||||||
|
)
|
||||||
return
|
return
|
||||||
self.__send_rtsp_response_ok(seq, "Public: DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN\r\n")
|
self.__send_rtsp_response_ok(
|
||||||
|
seq, "Public: DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN\r\n"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
elif request == "DESCRIBE":
|
elif request == "DESCRIBE":
|
||||||
payload = "v=0\r\no=- %d %d IN IP4 %s\r\ns=OpenMV Video\r\nt=0 0\r\nm=video 0 RTP/AVP 26" % (pyb.rng(), pyb.rng(), self.__myip)
|
payload = (
|
||||||
self.__send_rtsp_response_ok(seq, "Content-Type: application/sdp\r\nContent-Length: %d\r\n\r\n%s" % (len(payload) + 2, payload))
|
"v=0\r\no=- %d %d IN IP4 %s\r\ns=OpenMV Video\r\nt=0 0\r\nm=video 0 RTP/AVP 26"
|
||||||
|
% (pyb.rng(), pyb.rng(), self.__myip)
|
||||||
|
)
|
||||||
|
self.__send_rtsp_response_ok(
|
||||||
|
seq,
|
||||||
|
"Content-Type: application/sdp\r\nContent-Length: %d\r\n\r\n%s"
|
||||||
|
% (len(payload) + 2, payload),
|
||||||
|
)
|
||||||
return
|
return
|
||||||
elif request == "SETUP":
|
elif request == "SETUP":
|
||||||
if len(s) >= 3:
|
if len(s) >= 3:
|
||||||
m = re.match("Transport: RTP/AVP(/UDP)?;unicast;client_port=(\d+)-(\d+)", s[2])
|
m = re.match(
|
||||||
|
"Transport: RTP/AVP(/UDP)?;unicast;client_port=(\d+)-(\d+)", s[2]
|
||||||
|
)
|
||||||
if m:
|
if m:
|
||||||
self.__transport_is_tcp = False
|
self.__transport_is_tcp = False
|
||||||
self.__client_rtp_port = int(m.group(2))
|
self.__client_rtp_port = int(m.group(2))
|
||||||
self.__client_rtcp_port = int(m.group(3))
|
self.__client_rtcp_port = int(m.group(3))
|
||||||
self.__client_rtp_addr = (self.__client_addr[0], self.__client_rtp_port)
|
self.__client_rtp_addr = (
|
||||||
self.__client_rtcp_addr = (self.__client_addr[0], self.__client_rtcp_port)
|
self.__client_addr[0],
|
||||||
|
self.__client_rtp_port,
|
||||||
|
)
|
||||||
|
self.__client_rtcp_addr = (
|
||||||
|
self.__client_addr[0],
|
||||||
|
self.__client_rtcp_port,
|
||||||
|
)
|
||||||
self.__session = pyb.rng()
|
self.__session = pyb.rng()
|
||||||
self.__ssrc = pyb.rng()
|
self.__ssrc = pyb.rng()
|
||||||
self.__send_rtsp_response_ok(seq, "%s;server_port=%d-%d;ssrc=%d\r\nSession: %d\r\n" % (s[2], self.__client_rtp_port, self.__client_rtcp_port, self.__ssrc, self.__session))
|
self.__send_rtsp_response_ok(
|
||||||
if self.__setup_cb: self.__setup_cb(self.__pathname, self.__session)
|
seq,
|
||||||
|
"%s;server_port=%d-%d;ssrc=%d\r\nSession: %d\r\n"
|
||||||
|
% (
|
||||||
|
s[2],
|
||||||
|
self.__client_rtp_port,
|
||||||
|
self.__client_rtcp_port,
|
||||||
|
self.__ssrc,
|
||||||
|
self.__session,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if self.__setup_cb:
|
||||||
|
self.__setup_cb(self.__pathname, self.__session)
|
||||||
return
|
return
|
||||||
m = re.match("Transport: RTP/AVP/TCP;unicast;interleaved=(\d+)-(\d+)", s[2])
|
m = re.match(
|
||||||
|
"Transport: RTP/AVP/TCP;unicast;interleaved=(\d+)-(\d+)", s[2]
|
||||||
|
)
|
||||||
if m:
|
if m:
|
||||||
self.__transport_is_tcp = True
|
self.__transport_is_tcp = True
|
||||||
self.__client_rtp_channel = int(m.group(1))
|
self.__client_rtp_channel = int(m.group(1))
|
||||||
self.__client_rtcp_channel = int(m.group(2))
|
self.__client_rtcp_channel = int(m.group(2))
|
||||||
self.__session = pyb.rng()
|
self.__session = pyb.rng()
|
||||||
self.__ssrc = pyb.rng()
|
self.__ssrc = pyb.rng()
|
||||||
self.__send_rtsp_response_ok(seq, "%s\r\nSession: %d\r\n" % (s[2], self.__session))
|
self.__send_rtsp_response_ok(
|
||||||
if self.__setup_cb: self.__setup_cb(self.__pathname, self.__session)
|
seq, "%s\r\nSession: %d\r\n" % (s[2], self.__session)
|
||||||
|
)
|
||||||
|
if self.__setup_cb:
|
||||||
|
self.__setup_cb(self.__pathname, self.__session)
|
||||||
return
|
return
|
||||||
elif request == "PLAY":
|
elif request == "PLAY":
|
||||||
s = list(filter(lambda x: x and not x.startswith("Range"), s))
|
s = list(filter(lambda x: x and not x.startswith("Range"), s))
|
||||||
@ -140,8 +184,13 @@ class rtsp_server:
|
|||||||
m = re.match("Session: (\d+)", s[2])
|
m = re.match("Session: (\d+)", s[2])
|
||||||
if m:
|
if m:
|
||||||
self.__playing = True
|
self.__playing = True
|
||||||
self.__send_rtsp_response_ok(seq, "RTP-Info: url=%s;seq=%d\r\n" % (line0[1], self.__sequence_number))
|
self.__send_rtsp_response_ok(
|
||||||
if self.__play_cb: self.__play_cb(self.__pathname, int(m.group(1)))
|
seq,
|
||||||
|
"RTP-Info: url=%s;seq=%d\r\n"
|
||||||
|
% (line0[1], self.__sequence_number),
|
||||||
|
)
|
||||||
|
if self.__play_cb:
|
||||||
|
self.__play_cb(self.__pathname, int(m.group(1)))
|
||||||
return
|
return
|
||||||
elif request == "PAUSE":
|
elif request == "PAUSE":
|
||||||
if len(s) >= 3:
|
if len(s) >= 3:
|
||||||
@ -149,7 +198,8 @@ class rtsp_server:
|
|||||||
if m:
|
if m:
|
||||||
self.__playing = False
|
self.__playing = False
|
||||||
self.__send_rtsp_response_ok(seq)
|
self.__send_rtsp_response_ok(seq)
|
||||||
if self.__pause_cb: self.__pause_cb(self.__pathname, int(m.group(1)))
|
if self.__pause_cb:
|
||||||
|
self.__pause_cb(self.__pathname, int(m.group(1)))
|
||||||
return
|
return
|
||||||
elif request == "TEARDOWN":
|
elif request == "TEARDOWN":
|
||||||
if len(s) >= 3:
|
if len(s) >= 3:
|
||||||
@ -157,7 +207,8 @@ class rtsp_server:
|
|||||||
if m:
|
if m:
|
||||||
self.__playing = False
|
self.__playing = False
|
||||||
self.__send_rtsp_response_ok(seq)
|
self.__send_rtsp_response_ok(seq)
|
||||||
if self.__teardown_cb: self.__teardown_cb(self.__pathname, int(m.group(1)))
|
if self.__teardown_cb:
|
||||||
|
self.__teardown_cb(self.__pathname, int(m.group(1)))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.__send_rtsp_response_cseq(501, "Not Implemented", seq)
|
self.__send_rtsp_response_cseq(501, "Not Implemented", seq)
|
||||||
@ -165,49 +216,72 @@ class rtsp_server:
|
|||||||
self.__send_rtsp_response(400, "Bad Request")
|
self.__send_rtsp_response(400, "Bad Request")
|
||||||
|
|
||||||
def __valid_socket(self): # private
|
def __valid_socket(self): # private
|
||||||
if self.__transport_is_tcp: return self.__client_rtp_channel is not None
|
if self.__transport_is_tcp:
|
||||||
else: return self.__valid_udp_socket() and self.__client_rtp_addr is not None
|
return self.__client_rtp_channel is not None
|
||||||
|
else:
|
||||||
|
return self.__valid_udp_socket() and self.__client_rtp_addr is not None
|
||||||
|
|
||||||
def __settimeout(self, timeout): # private
|
def __settimeout(self, timeout): # private
|
||||||
if self.__transport_is_tcp: self.__tcp__socket.settimeout(timeout)
|
if self.__transport_is_tcp:
|
||||||
else: self.__udp__socket.settimeout(timeout)
|
self.__tcp__socket.settimeout(timeout)
|
||||||
|
else:
|
||||||
|
self.__udp__socket.settimeout(timeout)
|
||||||
|
|
||||||
def __send(self, data): # private
|
def __send(self, data): # private
|
||||||
if self.__transport_is_tcp: return self.__tcp__socket.send(struct.pack(">BBH", 0x24, self.__client_rtp_channel, len(data)) + data)
|
if self.__transport_is_tcp:
|
||||||
else: return self.__udp__socket.sendto(data, self.__client_rtp_addr)
|
return self.__tcp__socket.send(
|
||||||
|
struct.pack(">BBH", 0x24, self.__client_rtp_channel, len(data)) + data
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return self.__udp__socket.sendto(data, self.__client_rtp_addr)
|
||||||
|
|
||||||
def __close_socket(self): # private
|
def __close_socket(self): # private
|
||||||
if self.__transport_is_tcp: pass
|
if self.__transport_is_tcp:
|
||||||
else: self.__close_udp_socket()
|
pass
|
||||||
|
else:
|
||||||
|
self.__close_udp_socket()
|
||||||
|
|
||||||
def __send_rtp(self, image_callback, quality): # private
|
def __send_rtp(self, image_callback, quality): # private
|
||||||
img = image_callback(self.__pathname, self.__session).compress(quality)
|
img = image_callback(self.__pathname, self.__session).compress(quality)
|
||||||
if img.width() >= 2040: raise ValueError("Maximum width is 2040")
|
if img.width() >= 2040:
|
||||||
if img.height() >= 2040: raise ValueError("Maximum height is 2040")
|
raise ValueError("Maximum width is 2040")
|
||||||
|
if img.height() >= 2040:
|
||||||
|
raise ValueError("Maximum height is 2040")
|
||||||
i = 0
|
i = 0
|
||||||
l = img.size()
|
l = img.size()
|
||||||
rtp_header_size = 12
|
rtp_header_size = 12
|
||||||
jpeg_header_size = 8
|
jpeg_header_size = 8
|
||||||
max_packet_size = 1400 - rtp_header_size - jpeg_header_size
|
max_packet_size = 1400 - rtp_header_size - jpeg_header_size
|
||||||
if self.__transport_is_tcp: max_packet_size -= 4
|
if self.__transport_is_tcp:
|
||||||
|
max_packet_size -= 4
|
||||||
if self.__valid_socket():
|
if self.__valid_socket():
|
||||||
try:
|
try:
|
||||||
self.__settimeout(0.1)
|
self.__settimeout(0.1)
|
||||||
timestamp = (pyb.millis() * 90) & 0xFFFFFFFF
|
timestamp = (pyb.millis() * 90) & 0xFFFFFFFF
|
||||||
while l:
|
while l:
|
||||||
rtp_header = struct.pack(">BBHII",
|
rtp_header = struct.pack(
|
||||||
0x80, 0x9A if l <= max_packet_size else 0x1A,
|
">BBHII",
|
||||||
self.__sequence_number, timestamp, self.__ssrc)
|
0x80,
|
||||||
|
0x9A if l <= max_packet_size else 0x1A,
|
||||||
|
self.__sequence_number,
|
||||||
|
timestamp,
|
||||||
|
self.__ssrc,
|
||||||
|
)
|
||||||
self.__sequence_number = (self.__sequence_number + 1) & 0xFFFF
|
self.__sequence_number = (self.__sequence_number + 1) & 0xFFFF
|
||||||
jpeg_header = struct.pack(">IBBBB", i, 0, quality, int(img.width() // 8), int(img.height() // 8))
|
jpeg_header = struct.pack(
|
||||||
|
">IBBBB", i, 0, quality, int(img.width() // 8), int(img.height() // 8)
|
||||||
|
)
|
||||||
img_data = img.bytearray()[i : i + min(l, max_packet_size)]
|
img_data = img.bytearray()[i : i + min(l, max_packet_size)]
|
||||||
img_data_len = len(img_data)
|
img_data_len = len(img_data)
|
||||||
data_len = self.__send(rtp_header + jpeg_header + img_data)
|
data_len = self.__send(rtp_header + jpeg_header + img_data)
|
||||||
if not data_len: break
|
if not data_len:
|
||||||
|
break
|
||||||
i += img_data_len
|
i += img_data_len
|
||||||
l -= img_data_len
|
l -= img_data_len
|
||||||
if l: self.__close_socket()
|
if l:
|
||||||
except OSError: self.__close_socket()
|
self.__close_socket()
|
||||||
|
except OSError:
|
||||||
|
self.__close_socket()
|
||||||
|
|
||||||
def stream(self, image_callback, quality=90): # public
|
def stream(self, image_callback, quality=90): # public
|
||||||
while True:
|
while True:
|
||||||
@ -216,6 +290,9 @@ class rtsp_server:
|
|||||||
self.__tcp__socket.settimeout(0.1)
|
self.__tcp__socket.settimeout(0.1)
|
||||||
while True:
|
while True:
|
||||||
data = self.__tcp__socket.recv(1400)
|
data = self.__tcp__socket.recv(1400)
|
||||||
if data and len(data): self.__parse_rtsp_request(data)
|
if data and len(data):
|
||||||
if self.__playing: self.__send_rtp(image_callback, quality)
|
self.__parse_rtsp_request(data)
|
||||||
except OSError: self.__close_tcp_socket()
|
if self.__playing:
|
||||||
|
self.__send_rtp(image_callback, quality)
|
||||||
|
except OSError:
|
||||||
|
self.__close_tcp_socket()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user