matthewwall / weewx-interceptor

weewx driver that intercepts web traffic from internet 'bridge' devices such as Acurite Access, ObserverIP, OS LW30x, LaCross GW1000U, FineOffset GW1000
GNU General Public License v3.0
105 stars 44 forks source link

dictionary update sequence element #29 has length 1; 2 is required #118

Open JC1869 opened 9 months ago

JC1869 commented 9 months ago

Hello,

I have a sainlogic ws0300 pws that only supports sending to weatherunderground. I'm using dns redirection to send the updates to interceptor in wu-client listen mode. It appears the sainlogic POST adds a trailing & which is breaking everything. I used a packet capture to get the full URL and I can submit it without the trailing character from my browser and it succeeds. Is there a simple modification I can make somewhere to get past this?

Nov 20 12:59:27 weewx[18] ERROR user.interceptor: parse failed for ID=XXXXX&PASSWORD=YYYYY&indoortempf=69.1&indoorhumidity=36&tempf=39.8&humidity=77&temp1f=42.0&humidity1=74&dewptf=33.2&windchillf=37.7&absbaromin=24.49&baromin=30.04&windspeedmph=3.4&windgustmph=4.5&winddir=0&windspdmph_avg2m=3.8&winddir_avg2m=0&windgustmph_10m=2.7&windgustdir_10m=0&rainin=0.0&dailyrainin=0.11&weeklyrainin=0.39&monthlyrainin=0.39&solarradiation=121.58&UV=1&dateutc=2023-11-20%2019:59:27&action=updateraw&realtime=1&rtfreq=5&: dictionary update sequence element #29 has length 1; 2 is required Nov 20 12:59:27 weewx[18] DEBUG user.interceptor: raw packet: {} Nov 20 12:59:27 weewx[18] DEBUG user.interceptor: mapped packet: {} Nov 20 12:59:27 weewx[18] DEBUG user.interceptor: skipping bogus packet {} ('ID=XXXXX&PASSWORD=YYYYY&indoortempf=69.1&indoorhumidity=36&tempf=39.8&humidity=77&temp1f=42.0&humidity1=74&dewptf=33.2&windchillf=37.7&absbaromin=24.49&baromin=30.04&windspeedmph=3.4&windgustmph=4.5&winddir=0&windspdmph_avg2m=3.8&winddir_avg2m=0&windgustmph_10m=2.7&windgustdir_10m=0&rainin=0.0&dailyrainin=0.11&weeklyrainin=0.39&monthlyrainin=0.39&solarradiation=121.58&UV=1&dateutc=2023-11-20%2019:59:27&action=updateraw&realtime=1&rtfreq=5&')

JC1869 commented 9 months ago

I was able to fix this with the added s.rstrip('&') in interceptor.py:

def _cgi_to_dict(s): s=s.rstrip('&') if '=' in s: return dict([y.strip() for y in x.split('=')] for x in s.split('&')) return dict()

the-butterfry commented 7 months ago

Nice! Ok, adding this here for others. You had a trailing '&' issue. I had a Leading '&' issue.

ERROR user.interceptor: parse failed for &PASSKEY=xxxxxxxxxxxxxxxxxxx&stationtype=AMBWeatherPro_V5.1.4&dateutc=2024-01-21+19:30:33&tempf=45.3&humidity=99&windspeedmph=0.00&windgustmph=0.00&maxdailygust=5.82&winddir=54&uv=0&solarradiation=54.56&hourlyrainin=0.000&eventrainin=0.441&dailyrainin=0.181&weeklyrainin=0.181&monthlyrainin=4.232&yearlyrainin=4.232&totalrainin=26.961&battout=1&tempinf=67.1&humidityin=45&baromrelin=29.309&baromabsin=29.232&temp1f=58.8&humidity1=62&batt1=1: dictionary update sequence element #0 has length 1; 2 is required

To deal with the leading & just change your code to s=s.lstrip('&')

def _cgi_to_dict(s): s=s.lstrip('&') if '=' in s: return dict([y.strip() for y in x.split('=')] for x in s.split('&')) return dict()

ryan910 commented 7 months ago

Same issue here with a Ambient WS-1965 s=s.lstrip('&') fixed it for me