requires twisted + pyserial