Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    EHOSTUNREACH With PyCom AWS Tutorial

    Scheduled Pinned Locked Moved WiPy 2&3
    9 Posts 3 Posters 2.8k Views 3 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • N Offline
      noobiemcfoob Pybytes Beta
      last edited by

      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

      1 Reply Last reply Reply Quote 0
      • G Offline
        gertjanvanhethof Pybytes Beta
        last edited by

        Can you give us more details. For example, what is the output in you REPL window after a soft reboot?

        C N 2 Replies Last reply Reply Quote 0
        • C Offline
          crankshaft @gertjanvanhethof
          last edited by

          This post is deleted!
          1 Reply Last reply Reply Quote 0
          • N Offline
            noobiemcfoob Pybytes Beta @gertjanvanhethof
            last edited by

            @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?

            G 1 Reply Last reply Reply Quote 0
            • G Offline
              gertjanvanhethof Pybytes Beta @noobiemcfoob
              last edited by

              @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?

              N 1 Reply Last reply Reply Quote 0
              • N Offline
                noobiemcfoob Pybytes Beta @gertjanvanhethof
                last edited by

                @gertjanvanhethof :
                Here's demo.py

                import 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()
                
                
                
                G 1 Reply Last reply Reply Quote 0
                • G Offline
                  gertjanvanhethof Pybytes Beta @noobiemcfoob
                  last edited by

                  @noobiemcfoob

                  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?

                  G 1 Reply Last reply Reply Quote 0
                  • G Offline
                    gertjanvanhethof Pybytes Beta @gertjanvanhethof
                    last edited by

                    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.

                    N 1 Reply Last reply Reply Quote 0
                    • N Offline
                      noobiemcfoob Pybytes Beta @gertjanvanhethof
                      last edited by

                      @gertjanvanhethof

                      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.

                      1 Reply Last reply Reply Quote 0

                      Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                      Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                      With your input, this post could be even better 💗

                      Register Login
                      • 1 / 1
                      • First post
                        Last post

                      Pycom on Twitter

                      Pycom