简体   繁体   中英

Python http server can be reached from browser but not from pi pico

my python server is reachable from a browser but not from a pi pico client... this is my python server: server.py:

from http.server import BaseHTTPRequestHandler, HTTPServer
import time

import httphandler
import itemtype

HOST = "localhost"
PORT = 60001

class AirServer (httphandler.HttpHandler):

    AIR_TIME = 10 #* 60
    AIR_EARLY_START_HOUR = 9
    AIR_EARLY_END_HOUR = 16
    AIR_LATE_START_HOUR = 17 #19
    AIR_LATE_END_HOUR = 22
    MAX_HUMIDITY = 60

    request = None

    def delegate(self, command, params):
        if command.startswith("q"):
            command = "query"
            for param in params:
                if param.startswith("j"):
                    self.logJson = True
                elif param.startswith("v"):
                    self.logVerbose = True
                elif param.startswith("a"):
                    self.logAlertsOnly = True
        self.logStart(refresh=(command=="query" and "r" in params))
        if command != "query":
            if command.startswith("i"):
                command = "item"
            elif command.startswith("s"):
                command = "suppressalerts"
            else:
                self.logAlert("Unknown command: {}".format(command))
                return
        self.logCommand("Request: {}".format(self.path))
        if command == "query":
            self.delegateQuery(params)
        if command == "suppressalerts":
            self.delegateSuppressAlerts(params)
        elif command == "item":
            self.delegateItem(params)
        self.logFinish()

    def delegateQuery(self, params):
        for param in params:
            if param.startswith("j"):
                self.logJson = True
            elif param.startswith("v"):
                self.logVerbose = True
            elif param.startswith("a"):
                self.logAlertsOnly = True
        for id in AirServer.items.keys():
            item = AirServer.items.get(id)
            self.logHighlight(str(item))
            self.checkItem(item)
            if self.logVerbose:
                self.logSize = "small"
                for sample in item.samples:
                    self.log("\t{}".format(str(sample)))
                self.logSize = "medium"
        """if not self.logJson:
            for id in AirServer.items.keys():
                item = AirServer.items.get(id)
                self.logSize = "small"
                self.logLink("{}:{}/s/{}".format(AirServer.hostname, AirServer.port, id), "Suppress alerts for {}".format(id))
                self.logSize = "medium"
            for s in ("frueh", "spaet"):
                self.logSize = "small"
                self.logLink("{}:{}/s/{}".format(AirServer.hostname, AirServer.port, s), "Suppress alerts for {}".format(s))
                self.logSize = "medium"""

    def delegateSuppressAlerts(self, params):
        serverItem = AirServer.items.get("server")
        suppress = serverItem.getCurrent("suppress")
        if suppress is None:
            suppress = ""
        l = suppress.split("~")
        if params:
            l.extend(params)
        l_ = []
        for s in l:
            if len(s) > 0:
                l_.append(s)
        if l_:
            serverItem.addSample(["suppress", "~".join(l_)])

    def checkItem(self, item):
        if str(item.getCurrent("air")) == "1":
            # early air
            # late air
            # max air time
            openTimes = []
            t = None
            lastOpen = "0"
            for sample in item.samples:
                if sample.getCurrent("open") != lastOpen:
                    lastOpen = sample.getCurrent("open")
                    if lastOpen == "1":
                        t = sample.time
                    elif lastOpen == "0":
                        openTimes.append((t, sample.time - t))
            if lastOpen == "1":
                dt = time.time() - t
                if dt > self.AIR_TIME:
                    self.logAlert("{} {} offen fuer {}, muss geschlossen werden!".format(itemtype.fmtT(t), item.id, itemtype.fmtRT(dt), item.id))
                openTimes.append((t, dt))
            foundEarly = False
            foundLate = False
            for openTime in openTimes:
                if openTime[1] >= AirServer.AIR_TIME:
                    self.logHighlight("\t{} Lueftung fuer {}".format(itemtype.fmtT(openTime[0]), itemtype.fmtRT(openTime[1])))
                    hour = time.localtime(openTime[0]).tm_hour
                    if hour >= self.AIR_EARLY_START_HOUR and hour < self.AIR_EARLY_END_HOUR:
                        foundEarly = True
                    if hour >= self.AIR_LATE_START_HOUR and hour < self.AIR_LATE_END_HOUR:
                        foundLate = True
                else:
                    self.log("\t{} offen fuer {}".format(itemtype.fmtT(openTime[0]), itemtype.fmtRT(openTime[1])))
            hour = time.localtime().tm_hour
            if lastOpen != "1":
                if not foundEarly and hour >= self.AIR_EARLY_START_HOUR and hour < self.AIR_EARLY_END_HOUR:
                    self.logAlert("{} {} Noch keine fruehe Lueftung!".format(itemtype.fmtNow(), item.id))
                if not foundLate and hour >= self.AIR_LATE_START_HOUR and hour < self.AIR_LATE_END_HOUR:
                    self.logAlert("{} {} Noch keine spaete Lueftung!".format(itemtype.fmtNow(), item.id))
        humidity = item.getCurrent("humidity")
        if humidity is not None:
            humidity = int(humidity)
            if humidity > self.MAX_HUMIDITY:
                self.logAlert("{} {} Zu hohe Luftfeuchtigkeit, {}%!".format(itemtype.fmtNow(), item.id, humidity))

    def delegateItem(self, params):
        def usage():
            self.logAlert("Syntax error, usage: /item/id/key1/value1/key2/value2/...")
        if len(params) < 1:
            usage()
            return
        id = str(params[0])
        pairs = params[1:]
        if len(pairs) % 2 != 0:
            usage()
            return
        item = AirServer.items.get(id)
        if item.addSample(pairs):
            self.log(str(item))
        else:
            self.logAlert("Malformed sample")

if __name__ == "__main__":
    AirServer.start_(AirServer, hostname=HOST, port=PORT)

using this http handler: httphandler.py:

from http.server import BaseHTTPRequestHandler, HTTPServer

import itemtype

class HttpHandler (BaseHTTPRequestHandler):

    items = None

    DEFAULT_LOG_COLOR = "#bbb"
    ALERT_LOG_COLOR = "#f88"
    REFRESH_RATE = 2 #10

    logJson = None
    logVerbose = None
    logAlertsOnly = None
    logColor = None
    logSize = None
    logAlerts = None

    def header(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def do_HEAD(self):
        self.header()

    def do_GET(self):
        print("do_GET(): ")
        self.header()
        self.logInit()
        self.parse(self.path)

    def do_POST(self):
        print("do_POST(): ")
        self.header()
        self.logInit()
        self.parse(self.path)

    def parse(self, path):
        parts = path.split("/")
        if len(parts) < 2:
            return
        command = parts[1]
        params = parts[2:]
        self.delegate(command, params)

    def delegate(self, command, params):
        pass

    def logInit(self):
        self.logJson = False
        self.logVerbose = False
        self.logAlertsOnly = False
        self.logColor = self.DEFAULT_LOG_COLOR
        self.logSize = "medium"
        self.logAlerts = []

    def logStart(self, refresh=False):
        if self.logJson:
            self.wfile.write(bytes("[\n", "utf-8"))
        else:
            if refresh:
                self.wfile.write(bytes("<html>\n<head><title>AirServer</title><meta http-equiv=\"refresh\" content=\"{}\"></head>\n".format(self.REFRESH_RATE), "utf-8"))
            else:
                self.wfile.write(bytes("<html>\n<head><title>AirServer</title></head>\n", "utf-8"))
            self.wfile.write(bytes("<body style=\"font-family:'Lucida Console','Courier New',monospace;font-size:{};background-color:#234;color:{};\">\n".format(self.logSize, self.logColor), "utf-8"))

    def log(self, s):
        if self.logAlertsOnly and self.logColor != self.ALERT_LOG_COLOR:
            return
        if self.logJson:
            self.wfile.write(bytes("\t\"{}\",\n".format(s), "utf-8"))
        else:
            s = s.replace("\n", "<br/>\n").replace("\t", "&nbsp;&nbsp;")
            self.wfile.write(bytes("<div style=\"font-size:{};color:{};\">{}</div>\n".format(self.logSize, self.logColor, s), "utf-8"))

    def logAlert(self, s):
        suppress = HttpHandler.items.get("server").getCurrent("suppress")
        if suppress is not None:
            suppress = suppress.split("~")
            for token in suppress:
                if token.lower() in s.lower():
                    return
        self.logColor = self.ALERT_LOG_COLOR
        self.logAlerts.append(s)
        self.log(s)
        self.logColor = self.DEFAULT_LOG_COLOR

    def logHighlight(self, s):
        self.logColor = "#fff"
        self.log(s)
        self.logColor = self.DEFAULT_LOG_COLOR

    def logCommand(self, s):
        self.logColor = "#8f8"
        self.log(s)
        self.logColor = self.DEFAULT_LOG_COLOR

    def logLink(self, link, text):
        self.log("<a href=\"{}\" style=\"color:#484\">{}</a>".format(link, text))

    def logFinish(self):
        if self.logJson:
            self.wfile.write(bytes("\t\"terminated\"\n]\n", "utf-8"))
        else:
            self.logCommand("Terminated")
            self.wfile.write(bytes("</body>\n</html>\n", "utf-8"))

    @staticmethod
    def start(ServerClass, hostname="localhost", port=60001):
        print("Start server...")
        server = HTTPServer((hostname, port), ServerClass)
        HttpServer.hostname = hostname
        HttpServer.port = port
        print("Server started http://%s:%s" % (hostname, port))
        try:
            server.serve_forever()
        except KeyboardInterrupt:
            pass
        server.server_close()
        print("Server stopped")

    @staticmethod
    def start_(ServerClass, hostname="localhost", port=60001):
        with HTTPServer((hostname, port), ServerClass) as server:
            print("Server started http://%s:%s" % (hostname, port))
            server.serve_forever()

if HttpHandler.items is None:
    print("Init data...")
    HttpHandler.items = itemtype.Items()
    serverItem = HttpHandler.items.get("server")
    serverItem.addSample(["type", "server", "event", "start"])

this is my pi pico client:

import utime
import urequests

from led import Led
from wlan import Wlan

SSID = "M7"
PASSWORD = "blah"
HOST = "127.0.0.1"
PORT = 60001

led = Led("LED", value=0)

wlan = Wlan(SSID, PASSWORD)

wlan.connect()
if wlan.isConnected():
    led.on()
    print("connected")
    
    u = "http://{}:{}".format(HOST, PORT)
    print(u)
    r = urequests.get(url=u)
    print(r.text)
        
    wlan.disconnect()
    led.off()
    print("disconnected")

wlan.py:

import network
import utime

class Wlan (object):
    
    NUM_CHECK_FOR_CONNECT= 64
    CHECK_CONNECT_DELAY = 0.2
    CHECK_DISCONNECT_DELAY = CHECK_CONNECT_DELAY
    
    ssid = None
    password = None
    country = None
    
    wlan = None
    
    def __init__(self, ssid, password, country="DE"):
        self.ssid = ssid
        self.password = password
        self.country = country
        
    def isConnected(self):
        return not (not self.wlan.isconnected() and self.wlan.status() >= 0) #todo
    
    def isDisconnected(self):
        return not self.wlan.isconnected()
        
    def connect(self):
        self.wlan = network.WLAN(network.STA_IF)
        self.wlan.active(True)
        self.wlan.connect(self.ssid, self.password)
        for i in range(self.NUM_CHECK_FOR_CONNECT):
            if self.isConnected():
                break
            utime.sleep(self.CHECK_CONNECT_DELAY)
        return self.isConnected()
            
    def disconnect(self):
        self.wlan.disconnect()
        while not self.isDisconnected():
            utime.sleep(self.CHECK_DISCONNECT_DELAY)
        return True
        
if __name__ == "__main__":
    import machine
    led = machine.Pin("LED")
    led.off()
    
    wlan = Wlan("M7", "blah")
    print("connect...")
    wlan.connect()
    if wlan.isConnected():
        led.on()
        print("connected")
        wlan.disconnect()
        led.off()
        print("disconnected")
    else:
        print("failure")

i tried to reach the server via a browser and got a response. when i try to reach it via the pi pico i get

Traceback (most recent call last):
  File "<stdin>", line 23, in <module>
  File "urequests.py", line 180, in get
  File "urequests.py", line 91, in request
OSError: [Errno 113] EHOSTUNREACH

the connection to wlan does work. i also tried it with firewall off...

Change HOST = "localhost" to HOST = "0.0.0.0" in server.py - it should make the server available in the home network, whereas HOST = "localhost" only makes it available on the same machine. Then get the server's ip in the network (on Linux it can be done with ip addr or any other similar command). Try using this ip as HOST in the client code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM