EHOSTUNREACH With PyCom AWS Tutorial
-
I'm following the PyCom AWS Tutorial but am running into a EHOSTUNREACH error on the MQTT connect step.
I've verified my certs and host using a different MQTT client on the same network. When I call the run function from demo.py, it will hang in the connection loop. The first iteration will fail with "[Errno 113] EHOSTUNREACH". The rest fail with either an OSError: -32512 or OSError: 23
-
The '.pem' is more a convention in my office of labeling all certificate related files with that file type. It is the rootCA certificate.
I've been able to use the same certificate files to connect to AWS MQTT via a desktop client, so it shouldn't be an issue on the cloud side.
-
No it should be something else.
Try to make a connection to AWS using CLI and python library from a laptop.
Probably it's a security issue. I'am getting the same error now.
Give me some time, I will try to get it working and tell you how I solved it.
-
In you code I see: ca_certs='/flash/cert/rootCA.pem'
I think this should be a cert file and not the rootCA.pem.Besides this, do you really have a rootCA.pem instead of a rootCA.crt?
-
@gertjanvanhethof :
Here's demo.pyimport time from mqttclient import MQTTClient DISCONNECTED = 0 CONNECTING = 1 CONNECTED = 2 DEVICE_ID = "12345" HOST = "a33wjx7cetm2t9.iot.us-east-1.amazonaws.com" TOPIC_DOWNLOAD = "Download" TOPIC_UPLOAD = "Upload" state = DISCONNECTED connection = None def _recv_msg_callback(topic, msg): print("Received: {} from Topic: {}".format(msg, topic)) def _send_msg(msg): global connection connection.publish(TOPIC_UPLOAD, msg) def run(): global state global connection while True: # Wait for connection while state != CONNECTED: try: state = CONNECTING connection = MQTTClient(DEVICE_ID, server=HOST, port=8883) connection.connect(ssl=True, certfile='/flash/cert/certificate.key', keyfile='/flash/cert/private.key', ca_certs='/flash/cert/rootCA.pem') state = CONNECTED except Exception as e: print('Error connecting to the server: {}'.format(e)) time.sleep(0.5) continue print('Connected!') # Subscribe for messages connection.set_callback(_recv_msg_callback) connection.subscribe(TOPIC_DOWNLOAD) while state == CONNECTED: connection.check_msg() msg = '{"Name":"Pycom", "Data":"Test"}' print('Sending: ' + msg) _send_msg(msg) time.sleep(2.0)
and mqttclient:
import socket import struct import select from binascii import hexlify class MQTTException(Exception): pass class MQTTClient: def __init__(self, client_id, server, port=1883, user=None, password=None): self.client_id = client_id.encode('utf8') self.sock = None self.addr = socket.getaddrinfo(server, port)[0][-1] self.pid = 0 self.cb = None self.poll = select.poll() self.__will_message = None if user: self.__user = user.encode('utf8') else: self.__user = None self.__password = password def __encode_varlen_length(self, length): i = 0 buff = bytearray() while 1: buff.append(length % 128) length = length // 128 if length > 0: buff[i] = buff[i] | 0x80 i += 1 else: break return buff def __encode_16(self, x): return struct.pack("!H", x) def __pascal_string(self, s): return struct.pack("!H", len(s)) + s def __recv_varlen_length(self): m = 1 val = 0 while 1: b = self.sock.recv(1)[0] val += (b & 0x7F) * m m *= 128 if m > 2097152: # 128 * 128 * 128 raise MQTTException() if (b & 0x80) == 0: break return val def set_callback(self, f): self.cb = f def set_will(self, will_topic, will_message, will_qos=0, will_retain=0): if will_topic: self.__will_topic = will_topic.encode('utf8') self.__will_message = will_message self.__will_qos = will_qos self.__will_retain = will_retain def connect(self, clean_session=True, ssl=False, certfile=None, keyfile=None, ca_certs=None): try: self.poll.unregister(self.sock) except: pass self.sock = socket.socket() if ssl: import ssl self.sock = ssl.wrap_socket(self.sock, certfile=certfile, keyfile=keyfile, ca_certs=ca_certs, cert_reqs=ssl.CERT_REQUIRED) self.sock.connect(self.addr) self.poll.register(self.sock, select.POLLIN) pkt_len = (12 + len(self.client_id) + # 10 + 2 + len(client_id) (2 + len(self.__user) if self.__user else 0) + (2 + len(self.__password) if self.__password else 0)) flags = (0x80 if self.__user else 0x00) | (0x40 if self.__password else 0x00) | (0x02 if clean_session else 0x00) if self.__will_message: flags |= (self.__will_retain << 3 | self.__will_qos << 1 | 1) << 2 pkt_len += 4 + len(self.__will_topic) + len(self.__will_message) pkt = bytearray([0x10]) # connect pkt.extend(self.__encode_varlen_length(pkt_len)) # len of the remaining pkt.extend(b'\x00\x04MQTT\x04') # len of "MQTT" (16 bits), protocol name, and protocol version pkt.append(flags) pkt.extend(b'\x00\x00') # disable keepalive pkt.extend(self.__pascal_string(self.client_id)) if self.__will_message: pkt.extend(self.__pascal_string(self.__will_topic)) pkt.extend(self.__pascal_string(self.__will_message)) if self.__user: pkt.extend(self.__pascal_string(self.__user)) if self.__password: pkt.extend(self.__pascal_string(self.__password)) self.sock.send(pkt) resp = self.sock.recv(4) assert resp[0] == 0x20 and resp[1] == 0x02 if resp[3] != 0: raise MQTTException(resp[3]) return resp[2] & 1 def disconnect(self): self.sock.send(b"\xe0\0") self.sock.close() def ping(self): self.sock.send(b"\xc0\0") def publish(self, topic, msg, retain=False, qos=0, dup=0): topic = topic.encode('utf8') hdr = 0x30 | (dup << 3) | (qos << 1) | retain pkt_len = (2 + len(topic) + (2 if qos else 0) + (len(msg))) pkt = bytearray() pkt.append(hdr) pkt.extend(self.__encode_varlen_length(pkt_len)) # len of the remaining pkt.extend(self.__pascal_string(topic)) if qos: self.pid += 1 #todo: I don't think this is the way to deal with the packet id pkt.extend(self.__encode_16(self.pid)) self.sock.send(pkt) self.sock.send(msg) #todo: check next part of the code if qos == 1: while 1: rcv_pid = self.recv_pubconf(0) if pid == rcv_pid: return elif qos == 2: assert 0 def recv_pubconf(self, t): headers = [0x40, 0x50, 0x62, 0x70] header = headers[t] while 1: op = self.wait_msg() if op == header: sz = self.sock.recv(1) assert sz == b"\x02" return def subscribe(self, topic, qos=0): assert self.cb is not None, "Subscribe callback is not set" topic = topic.encode('utf8') pkt_len = 2 + 2 + len(topic) + 1 # packet identifier + len of topic (16 bits) + topic len + QOS self.pid += 1 pkt = bytearray([0x82]) pkt.extend(self.__encode_varlen_length(pkt_len)) # len of the remaining pkt.extend(self.__encode_16(self.pid)) pkt.extend(self.__pascal_string(topic)) pkt.append(qos) self.sock.send(pkt) resp = self.sock.recv(5) #print(resp) assert resp[0] == 0x90 assert resp[2] == pkt[2] and resp[3] == pkt[3] if resp[4] == 0x80: raise MQTTException(resp[4]) # Wait for a single incoming MQTT message and process it. # Subscribed messages are delivered to a callback previously # set by .set_callback() method. Other (internal) MQTT # messages processed internally. def wait_msg(self): res = self.sock.recv(1) self.sock.setblocking(True) if res is None or res == b"": return None #if res == b"": # raise OSError(-1) if res == b"\xd0": # PINGRESP sz = self.sock.recv(1)[0] assert sz == 0 return None op = res[0] if op & 0xf0 != 0x30: return op sz = self.__recv_varlen_length() topic_len = self.sock.recv(2) topic_len = (topic_len[0] << 8) | topic_len[1] topic = self.sock.recv(topic_len) sz -= topic_len + 2 if op & 6: pid = self.sock.recv(2) pid = pid[0] << 8 | pid[1] sz -= 2 msg = self.sock.recv(sz) self.cb(topic, msg) if op & 6 == 2: pkt = bytearray(b"\x40\x02\0\0") struct.pack_into("!H", pkt, 2, pid) self.sock.send(pkt) elif op & 6 == 4: assert 0 # Checks whether a pending message from server is available. # If not, returns immediately with None. Otherwise, does # the same processing as wait_msg. def check_msg(self): self.sock.setblocking(False) return self.wait_msg()
-
@noobiemcfoob Could you also share demo.py with us.
WiFi logging from REPL seems ok to me. So it should be something else.
Are you using a guest wifi in which you should also provide username, password to logon?
-
@gertjanvanhethof, sure. Here's the REPL output following reset showing the WiPy connecting to my network (Cisco02775). I was able to verify the connection by pinging the WiPy on the network from a different device.
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0x00 clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:QIO, clock div:2 load:0x3fff9010,len:8 load:0x3fff9018,len:268 ho 0 tail 12 room 4 load:0x40078000,len:2656 load:0x4009f000,len:2040 entry 0x4009f12c tcpip_task_hdlxxx : 3ffd4530, prio:18,stack:2048 I (1698) wifi: frc2_timer_task_hdl:3ffd7b48, prio:22, stack:2048 I (1703) wifi: pp_task_hdl : 3ffda3f8, prio:23, stack:8192 I (1703) wifi: sleep disable I (2678) wifi: mode : softAP (24:0a:c4:00:a4:f7) dhcp server start:(ip: 192.168.4.1, mask: 255.255.255.0, gw: 192.168.4.1) I (2758) wifi: sleep enable I (2759) wifi: type: 1 I (2759) wifi: mode : sta (24:0a:c4:00:a4:f6) MicroPython v1.8.6-422-g516b861 on 2017-02-07; WiPy with ESP32 Type "help()" for more information. >>> I (6561) wifi: n:6 0, o:6 0, ap:255 255, sta:6 0, prof:6 I (7535) wifi: state: init -> auth (b0) I (7537) wifi: state: auth -> assoc (0) I (7541) wifi: state: assoc -> run (10) I (7559) wifi: connected with Cisco02775, channel 6 I (17541) wifi: pm start, type:1 >>> from demo import * >>> run() Error connecting to the server: [Errno 113] EHOSTUNREACH Error connecting to the server: -32512 Error connecting to the server: -32512 Error connecting to the server: -32512 Error connecting to the server: -32512 Error connecting to the server: -32512 Error connecting to the server: -32512 Error connecting to the server: -16912 Error connecting to the server: -10368 Error connecting to the server: -10368 Error connecting to the server: -10368 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Error connecting to the server: 23 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "demo.py", line 38, in run KeyboardInterrupt: >>>
Is there anything else I could provide as a clue?
-
This post is deleted!
-
Can you give us more details. For example, what is the output in you REPL window after a soft reboot?