0

I have a client class, in which it should connect to the server (in this case, iKettle) and sends and receives data. The IP address should come from another main server (so another class), and this IP address can change.

Below is the client code:

#command codes
_ON = "0x4<LF>"
_OFF = "0x0<LF>"

#base command
_BASE_COMMAND = "set sys output "

_SLEEP_TIME = 0.5

#size of buffer when receiving data
_BUFFER_SIZE = 1024
ip_address = ""
port = 2000

def initialiseSocket(self,ip_address):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, self.port))
    return s

def setOn(self,ip_address):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, self.port))
    s.send("set sys output 0x4<LF>")
    time.sleep(self._SLEEP_TIME)
    self.kettleResponse(ip_address)

def setOff(self,ip_address):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, self.port))
    s.send(self._BASE_COMMAND + self._OFF)
    time.sleep(self._SLEEP_TIME)
    self.kettleResponse(ip_address)

def kettleResponse(self,ip_address):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, self.port))
    data = s.recv(self._BUFFER_SIZE)
    print(data)

And this is an example of commands from another class:

kettle.setOn(KETTLEIP)

However, when running this code, it does not print anything.

Can anyone help please?

8
  • Can you tell us what this program does manage to achieve? Your example of calling kettle.setOn(KETTLEIP) seems like it should run until print(data), but you say there is no printout. Does the code get stuck somewhere? Commented Feb 17, 2018 at 19:00
  • btw, you have not included all your code. I suspect it should start with class Kettle: Commented Feb 17, 2018 at 19:02
  • "it does not print anything." - why should it? There is no output statement anywhere in the code you've shown. Commented Feb 17, 2018 at 19:12
  • Yes correct, it does start with class Kettle: but I just removed that bit, and when it runs, it runs endlessly, without a stop and it's supposed to boil the kettle and say kettle boiled but doesn't say it Commented Feb 17, 2018 at 20:49
  • and there is output statement in kettleResponse Commented Feb 17, 2018 at 20:50

2 Answers 2

1

You're probably connecting and reconnecting too much. Sometimes that simplifies things, but in this case I believe it's making you lose your response.

Try just connecting once, and reusing the socket.

Also, keep in mind that TCP is a byte-oriented protocol, not a message-oriented protocol. IOW, if you send 10k, 10k, 10k, the other side of the TCP socket may receive 5k, 8k, 17k - or even more bizarre possibilities. The total number of bytes will be the same, and the data will arrive in the correct order, but the sizes of the chunks could be totally scrambled. For this reason, most folks use REST with http these days - it's simpler in some ways.

If you're married to TCP, perhaps try my bufsock module (or actually, it's Opensource with a Univ Calif Irvine copyright, but I wrote it while I was working for them, and obtained permission from them to release it). It's at http://stromberg.dnsalias.org/~strombrg/bufsock.html . Its methods behave closer to what most people expect out of TCP.

HTH.

Sign up to request clarification or add additional context in comments.

1 Comment

How do I reuse the socket?
0

My guess is that you should reuse the socket as @dstromberg indicates:

class Kettle:
    # other stuff omitted...

    def setOn(self,ip_address):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip_address, self.port))
        s.send("set sys output 0x4<LF>")
        time.sleep(self._SLEEP_TIME)
        self.kettleResponse(s) # pass the socket on

    def kettleResponse(self, s):
        # don't open a new socket, just reuse s
        data = s.recv(self._BUFFER_SIZE)
        print(data)

5 Comments

so do I add this to every method? e.g. setOff?
I just tried it, and it didn't fix it, still isn't receiving response
Probably. Anyway it looks like you ought to extract out a method like: def setCommand(self, ip_address, command): which sends the command and prints the response.
Perhaps you should start with a simpler 'HELLOKETTLE' program: awe.com/mark/blog/20140223.html
Ok, I just noticed that you have to send a '\n' after each command, eg.where you have "set sys output 0x4<LF>" it should be: "set sys output 0x4\n"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.