Skip to content

Commit 1b3b6f8

Browse files
authored
Merge pull request #1 from micropython/master
Syncing with Original
2 parents 9dfde97 + 4a8ef9f commit 1b3b6f8

File tree

7 files changed

+110
-10
lines changed

7 files changed

+110
-10
lines changed

umqtt.robust/example_sub_robust.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import time
2+
from umqtt.robust import MQTTClient
3+
4+
5+
def sub_cb(topic, msg):
6+
print((topic, msg))
7+
8+
9+
c = MQTTClient("umqtt_client", "localhost")
10+
# Print diagnostic messages when retries/reconnects happens
11+
c.DEBUG = True
12+
c.set_callback(sub_cb)
13+
# Connect to server, requesting not to clean session for this
14+
# client. If there was no existing session (False return value
15+
# from connect() method), we perform the initial setup of client
16+
# session - subscribe to needed topics. Afterwards, these
17+
# subscriptions will be stored server-side, and will be persistent,
18+
# (as we use clean_session=False).
19+
#
20+
# There can be a problem when a session for a given client exists,
21+
# but doesn't have subscriptions a particular application expects.
22+
# In this case, a session needs to be cleaned first. See
23+
# example_reset_session.py for an obvious way how to do that.
24+
#
25+
# In an actual application, it's up to its developer how to
26+
# manage these issues. One extreme is to have external "provisioning"
27+
# phase, where initial session setup, and any further management of
28+
# a session, is done by external tools. This allows to save resources
29+
# on a small embedded device. Another extreme is to have an application
30+
# to perform auto-setup (e.g., clean session, then re-create session
31+
# on each restart). This example shows mid-line between these 2
32+
# approaches, where initial setup of session is done by application,
33+
# but if anything goes wrong, there's an external tool to clean session.
34+
if not c.connect(clean_session=False):
35+
print("New session being set up")
36+
c.subscribe(b"foo_topic")
37+
38+
while 1:
39+
c.wait_msg()
40+
41+
c.disconnect()

umqtt.robust/umqtt/robust.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import utime
2+
from . import simple
3+
4+
class MQTTClient(simple.MQTTClient):
5+
6+
DELAY = 2
7+
DEBUG = False
8+
9+
def delay(self, i):
10+
utime.sleep(self.DELAY)
11+
12+
def log(self, in_reconnect, e):
13+
if self.DEBUG:
14+
if in_reconnect:
15+
print("mqtt reconnect: %r" % e)
16+
else:
17+
print("mqtt: %r" % e)
18+
19+
def reconnect(self):
20+
i = 0
21+
while 1:
22+
try:
23+
return super().connect(False)
24+
except OSError as e:
25+
self.log(True, e)
26+
i += 1
27+
self.delay(i)
28+
29+
def publish(self, topic, msg, retain=False, qos=0):
30+
while 1:
31+
try:
32+
return super().publish(topic, msg, retain, qos)
33+
except OSError as e:
34+
self.log(False, e)
35+
self.reconnect()
36+
37+
def wait_msg(self):
38+
while 1:
39+
try:
40+
return super().wait_msg()
41+
except OSError as e:
42+
self.log(False, e)
43+
self.reconnect()

umqtt.simple/README.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ API reference
4646
Taking into account API traits described above, umqtt pretty closely
4747
follows MQTT control operations, and maps them to class methods:
4848

49-
* ``connect()`` - Connect to a server.
49+
* ``connect(...)`` - Connect to a server. Returns True if this connection
50+
uses persisten session stored on a server (this will be always False if
51+
clean_session=True argument is used (default)).
5052
* ``disconnect()`` - Disconnect from a server, release resources.
5153
* ``ping()`` - Ping server (response is processed automatically by wait_msg()).
5254
* ``publish()`` - Publish a message.

umqtt.simple/umqtt/simple.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,20 @@ def ping(self):
5555
self.sock.close()
5656

5757
def publish(self, topic, msg, retain=False, qos=0):
58-
pkt = bytearray(b"\x30\0\0")
58+
pkt = bytearray(b"\x30\0\0\0")
5959
pkt[0] |= qos << 1 | retain
6060
sz = 2 + len(topic) + len(msg)
6161
if qos > 0:
6262
sz += 2
63-
assert sz <= 16383
64-
pkt[1] = (sz & 0x7f) | 0x80
65-
pkt[2] = sz >> 7
63+
assert sz < 2097152
64+
i = 1
65+
while sz > 0x7f:
66+
pkt[i] = (sz & 0x7f) | 0x80
67+
sz >>= 7
68+
i += 1
69+
pkt[i] = sz
6670
#print(hex(len(pkt)), hexlify(pkt, ":"))
67-
self.sock.write(pkt)
71+
self.sock.write(pkt, i + 1)
6872
self._send_str(topic)
6973
if qos > 0:
7074
self.pid += 1
@@ -108,9 +112,9 @@ def subscribe(self, topic, qos=0):
108112
# messages processed internally.
109113
def wait_msg(self):
110114
res = self.sock.read(1)
115+
self.sock.setblocking(True)
111116
if res is None:
112117
return None
113-
self.sock.setblocking(True)
114118
if res == b"":
115119
raise OSError(-1)
116120
if res == b"\xd0": # PINGRESP

upysh/metadata.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
srctype = micropython-lib
22
type = module
3-
version = 0.4
3+
version = 0.5
44
author = Paul Sokolovsky
55
desc = Minimalistic file shell using native Python syntax.
66
long_desc = Minimalistic file shell using native Python syntax.

upysh/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77

88
setup(name='micropython-upysh',
9-
version='0.4',
9+
version='0.5',
1010
description='Minimalistic file shell using native Python syntax.',
1111
long_description='Minimalistic file shell using native Python syntax.',
1212
url='https://github.com/micropython/micropython/issues/405',

upysh/upysh.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,17 @@ def __repr__(self):
2525
def __call__(self):
2626
return self.__repr__()
2727

28+
class CLEAR:
29+
def __repr__(self):
30+
return "\x1b[2J\x1b[H"
31+
32+
def __call__(self):
33+
return self.__repr__()
34+
35+
2836
pwd = PWD()
2937
ls = LS()
38+
clear = CLEAR()
3039

3140
cd = os.chdir
3241
mkdir = os.mkdir
@@ -66,7 +75,8 @@ def __repr__(self):
6675
6776
upysh commands:
6877
pwd, cd("new_dir"), ls, ls(...), head(...), cat(...)
69-
newfile(...), rm(...), mkdir(...), rmdir(...)
78+
newfile(...), rm(...), mkdir(...), rmdir(...),
79+
clear
7080
""")
7181

7282
man = Man()

0 commit comments

Comments
 (0)