Skip to content

Commit

Permalink
fixes for ws 5000/obersveriop oddities with new firmware updates
Browse files Browse the repository at this point in the history
  • Loading branch information
tlskinneriv committed Sep 9, 2023
1 parent 4453b3c commit b7aa398
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 37 deletions.
40 changes: 23 additions & 17 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,28 @@
"containerEnv": {
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
},
"extensions": [
"timonwong.shellcheck",
"esbenp.prettier-vscode",
"RLNT.keep-a-changelog"
],
"mounts": ["type=volume,target=/var/lib/docker"],
"settings": {
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "/usr/bin/zsh"
"customizations": {
"vscode": {
"extensions": [
"timonwong.shellcheck",
"esbenp.prettier-vscode",
"RLNT.keep-a-changelog",
"ms-python.python",
"ms-python.vscode-pylance"
],
"settings": {
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "/usr/bin/zsh"
}
},
"terminal.integrated.defaultProfile.linux": "zsh",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true
}
},
"terminal.integrated.defaultProfile.linux": "zsh",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true
}
}
},
"mounts": ["type=volume,target=/var/lib/docker"]
}
10 changes: 10 additions & 0 deletions awnet/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

All notable changes to this project will be documented in this file.

## [1.0.1] - 2023-09-09

### Changed

- Update the way that malformed requests are handled: instead of assuming that the data will be
parsed into the headers, look for the broken request string and reassemble it. Limit to 3 lines of
lookahead to prevent server blocking if the request is highly malformed.
- HOUSEKEEPING: Updated base container to python3.11/alpine3.18.
- HOUSEKEEPING: Updated devcontainer config to be compliant with current VS Code recommendations.

## [1.0.0] - 2023-03-02

### Added
Expand Down
4 changes: 1 addition & 3 deletions awnet/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ ENV LANG C.UTF-8
# Copy data for add-on
COPY rootfs /
RUN chmod a+x /run.sh
RUN apk add --no-cache python3 py3-pip
RUN python3 -m pip install requests

CMD [ "/run.sh" ]
#ENTRYPOINT ["tail", "-f", "/dev/null"]
CMD [ "/run.sh" ]
12 changes: 5 additions & 7 deletions awnet/build.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-dockerfile

build_from:
aarch64: "ghcr.io/home-assistant/aarch64-base:3.15"
amd64: "ghcr.io/home-assistant/amd64-base:3.15"
armhf: "ghcr.io/home-assistant/armhf-base:3.15"
armv7: "ghcr.io/home-assistant/armv7-base:3.15"
i386: "ghcr.io/home-assistant/i386-base:3.15"
aarch64: "ghcr.io/home-assistant/aarch64-base-python:3.11-alpine3.18"
amd64: "ghcr.io/home-assistant/amd64-base-python:3.11-alpine3.18"
armhf: "ghcr.io/home-assistant/armhf-base-python:3.11-alpine3.18"
armv7: "ghcr.io/home-assistant/armv7-base-python:3.11-alpine3.18"
i386: "ghcr.io/home-assistant/i386-base-python:3.11-alpine3.18"
labels:
org.opencontainers.image.title: "Home Assistant Add-on: AWNET to HASS"
org.opencontainers.image.description: "Addon to capture local Ambient Weather data in Home Assistant"
org.opencontainers.image.source: "https://github.com/tlskinneriv/hassio-addons"
org.opencontainers.image.licenses: "MIT License"
args:
TEMPIO_VERSION: "2021.09.0"
2 changes: 1 addition & 1 deletion awnet/config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: AWNET to HASS
version: 1.0.0
version: 1.0.1
slug: awnet_to_hass
description: Addon to capture local Ambient Weather data in Home Assistant
arch:
Expand Down
51 changes: 42 additions & 9 deletions awnet/rootfs/awnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
# original author: Austin of austinsnerdythings.com
# publish date: 2021-03-20

from urllib.parse import parse_qs, quote
from urllib.parse import parse_qs
from wsgiref.headers import Headers
from wsgiref.simple_server import WSGIRequestHandler
import re
import json
import requests
import os
Expand Down Expand Up @@ -72,13 +74,6 @@ def application(environ, start_response):
headers = get_headers(environ)
_LOGGER.debug("Headers: \n\n%s", headers)
result = parse_qs(environ["QUERY_STRING"])
_LOGGER.debug("Data: %s", result)
ws5000_header = [(header, value) for header, value in headers.items() if header.startswith('&STATIONTYPE')]
_LOGGER.debug("WS-5000 Header: %s", ws5000_header)
if len(ws5000_header) == 1:
ws5000_result = {key.lower():value for key, value in parse_qs(':'.join(ws5000_header[0]).lstrip('&').split(' ')[0]).items()}
_LOGGER.debug("WS-5000 Extra Data: %s", ws5000_result)
result = result | ws5000_result
_LOGGER.debug("Full Data: %s", result)
# send to our other function to deal with the results.
# result is a dict
Expand All @@ -103,6 +98,44 @@ def application(environ, start_response):
# Apache/Python WSGI will run the function 'application()' directly
# in theory, you don't need apache or any web server. just run it right out of python. would need
# to improve error handling to ensure it run without interruption.

class AWNETWSGIRequestHandler(WSGIRequestHandler):
def parse_request(self):
"""
Adds in logic to handle the poorly formed (non-compliant) request strings that some Ambient Weather devices send.
"""
requestline = str(self.raw_requestline, 'iso-8859-1')
requestline = requestline.rstrip('\r\n')
_LOGGER.debug("original requestline: %s", requestline)
extra_lines_read = 0
while re.search(pattern=r'\s+HTTP/\d+\.\d+$', string=requestline, flags=re.IGNORECASE) is None:
if extra_lines_read == 3:
_LOGGER.warning("3 extra lines read to detect querystring, but still not detected properly. Aborting extra line reads.")
break
raw_extraline = self.rfile.readline(65537)
if len(raw_extraline) > 65536:
self.requestline = ''
self.request_version = ''
self.command = ''
self.send_error(414)
return
extraline = str(raw_extraline, 'iso-8859-1')
extraline = extraline.rstrip('\r\n')
_LOGGER.debug("extraline: %s", extraline)
requestline += extraline
extra_lines_read += 1
if extra_lines_read > 0:
new_raw_requestline = requestline.encode('iso-8859-1')
if len(new_raw_requestline) > 65536:
self.requestline = ''
self.request_version = ''
self.command = ''
self.send_error(414)
return
self.raw_requestline = new_raw_requestline
_LOGGER.debug("new raw_requestline: %s", self.raw_requestline)
return super().parse_request()

if __name__ == "__main__":
from wsgiref.simple_server import make_server

Expand All @@ -111,7 +144,7 @@ def application(environ, start_response):
level = sys.argv[1])

# probably shouldn't run on port 80 but that's what I specified in the ambient weather console
httpd = make_server("", 80, application)
httpd = make_server("", 80, application, handler_class=AWNETWSGIRequestHandler)
_LOGGER.info("Serving on http://localhost:80")

httpd.serve_forever()

0 comments on commit b7aa398

Please sign in to comment.