changeset 412:65b0dc335243

unfuck lightsc.py
author Louis Opter <kalessin@kalessin.fr>
date Fri, 01 Jan 2016 13:15:41 +0100
parents dadccf117097
children 9067c2da9572
files fix_lightscpy_readloop.patch series
diffstat 2 files changed, 76 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fix_lightscpy_readloop.patch	Fri Jan 01 13:15:41 2016 +0100
@@ -0,0 +1,75 @@
+# HG changeset patch
+# Parent  c8614ad2dc1133c8d50e974afd66d84231b41c78
+FIx lightsc.py's read loop
+
+We do need to do non-blocking IO in case the last received buffer comes
+back full in this case doing another read would block the whole thing.
+
+diff --git a/examples/lightsc.py b/examples/lightsc.py
+--- a/examples/lightsc.py
++++ b/examples/lightsc.py
+@@ -30,9 +30,11 @@
+ 
+ import argparse
+ import contextlib
++import fcntl
+ import json
+ import locale
+ import os
++import select
+ import socket
+ import subprocess
+ import sys
+@@ -42,6 +44,9 @@
+ 
+ class LightsClient:
+ 
++    READ_SIZE = 4096
++    ENCODING = "utf-8"
++
+     def __init__(self, url):
+         self.url = url
+ 
+@@ -56,6 +61,7 @@
+         else:
+             raise ValueError("Unsupported url {}".format(url))
+ 
++        fcntl.fcntl(self._socket, fcntl.F_SETFL, os.O_NONBLOCK)
+         self._pipeline = []
+         self._batch = False
+ 
+@@ -75,17 +81,27 @@
+         }
+ 
+     def _execute_payload(self, payload):
+-        print(payload)
+-        self._socket.send(json.dumps(payload).encode("utf-8"))
+-        # FIXME: proper read loop
+-        response = self._socket.recv(64 * 1024).decode("utf-8")
++        select.select([], [self._socket], [])
++        payload = json.dumps(payload).encode(self.ENCODING, "surrogateescape")
++        self._socket.send(payload)
++
++        response = bytearray()
++        select.select([self._socket], [], [])
++        while True:
++            try:
++                part = self._socket.recv(self.READ_SIZE)
++            except BlockingIOError:
++                break
++            if not part:
++                break
++            response += part
++
++        response = response.decode(self.ENCODING, "surrogateescape")
+         try:
+-            response = json.loads(response)
++            return json.loads(response)
+         except Exception:
+             print("received invalid json: {}".format(response))
+ 
+-        return response
+-
+     def _jsonrpc_call(self, method, params):
+         payload = self._make_payload(method, params)
+         if self._batch:
--- a/series	Thu Dec 31 15:34:49 2015 +0100
+++ b/series	Fri Jan 01 13:15:41 2016 +0100
@@ -3,6 +3,7 @@
 network_discovery.patch
 dont_use_ev_assign.patch
 add_power_transition.patch
+fix_lightscpy_readloop.patch
 open_gateway_on_any_bulb_response.patch #+future
 make_gateway_write_callbacks_low_priority.patch #+future
 use_echo_request_reply_to_measure_latency.patch #+future