diff --git a/lmwsip.py b/lmwsip.py index accc90c..b580065 100644 --- a/lmwsip.py +++ b/lmwsip.py @@ -4,8 +4,10 @@ See: LmwSip""" import socket import ssl +import select import time import re +import logging class LmwSip: """Class to connect to the LMW Standard Interface prototcol (sip) @@ -23,9 +25,9 @@ Support for: """ def __init__(self, user=None, password=None, - host="sip-lmw.rws.nl", port=443, - meetnet="LMW", ssl = True, check_ssl = True): - """LmwSip(user, password, [host], [port], [meetnet], [ssl], [check_ssl]) + host="sip-lmw.rws.nl", port=443, meetnet="LMW", ssl = True, + check_ssl = True, timeout = 10, log = None): + """LmwSip(user, password, [host], [port], [meetnet], [ssl], [check_ssl], [timeout], [log]) user(optinal): Lmw user name password(optional): Lmw password @@ -34,6 +36,8 @@ port(optional): Default 443 meetnet(optional): Default LMW ssl(optional): Default true check_ssl(optional): true +timeout(optional): 10 +log(optional): None Opens the connection and logs in """ @@ -44,6 +48,17 @@ Opens the connection and logs in self.meetnet = meetnet self.ssl = ssl self.check_ssl = check_ssl + self.timeout = timeout + self._socket = None + if (log != None): + self.log = log + self.log.debug("LmwSip.init") + else: + try: + self.log = logging.getLogger("lmwsip") + self.log.debug("LmwSip.init: Start log") + except Exception as e: + print("Logger failed: %s" % e) if (self.host != None): self.connect() if (self.user != None): @@ -85,22 +100,51 @@ Opens the connection and logs in connects to lmw with tcp using the values of the object creation. """ - self._tcp = socket.create_connection((self.host, self.port)) + try: + self._tcp = socket.create_connection((self.host, self.port)) + except Exception as e: + self.log.error("LmwSip.connect(%s, %s) failed: %s", + self.host, self.port, e) + raise LmwSipConnectError("LmwSip.connect: Socket create failed") if (self.ssl): - self._context = ssl.create_default_context() - self._context.check_hostname = self.check_ssl - self._ssl = self._context.wrap_socket(self._tcp, + try: + self._context = ssl.create_default_context() + self._context.check_hostname = self.check_ssl + self._ssl = self._context.wrap_socket(self._tcp, server_hostname=self.host) - self._socket = self._ssl + self._socket = self._ssl + except Exception as e: + self.log.error("LmwSip.connect setup ssl failed:\n%s", e) + raise LmwSipConnectError("LmwSip.connect: setup ssl failed") else: self._socket = self._tcp + self._socket.settimeout(self.timeout) + + def closesocket(self): + """Closes the socket and set the socket to None. Doesn't logout""" + + try: + self.log.debug("LmwSip.closesocket") + self._socket.close() + except Exception as e: + pass + self._socket = None def send(self, sipcmd): """send(sipcmd) send a sip command to the server """ - self._socket.sendall(sipcmd.encode('ascii')) + if self._socket != None: + try: + self.log.debug("LmwSip.send(%s)" % sipcmd) + self._socket.sendall(sipcmd.encode('ascii')) + except Exception as e: + self.log.error("LmwSip.send(%s) failed: %s", sipcmd, e) + self.closesocket() + raise LmwSipConnectError("LmwSip.send: Socket connection lost") + else: + self.log.warn("LmwSip.send: No connection") def recv(self): """recv() @@ -108,8 +152,26 @@ send a sip command to the server recieve a answer from the sip server """ buf="" - while re.search("\r$", buf) == None: - buf += self._socket.recv(4096).decode('utf-8') + while self._socket != None and re.search("\r$", buf) == None: + try: + self.log.debug("LmwSip.recv: Waiting for data"); + b = self._socket.recv(4096).decode('utf-8') + if (b == ""): + self.log.error("SipLmw.recv: socket closed") + self.closesocket() + raise LmwSipConnectError("LmwSip.recv: Socket close") + else: + buf += b + except Exception as e: + self.log.error("SipLmw.recv: socket timeout: %s", e) + self.closesocket() + raise LmwSipConnectError("LmwSip.recv: Socket timeout") + if self._socket == None: + self.log.warn("LmwSip.recv: No connection") + elif buf[0] != '!': + self.log.warn("LmwSip.recv: Sip error: %s" % buf) + else: + self.log.debug("LmwSip.recv: result: %s" % buf) return(buf) def login(self): @@ -135,7 +197,7 @@ Raises a LmwCmdWarn of failure self.send(ti) d = self.recv() if (d('ascii')[0] != '!'): - raise LmwCmdWarn("TI " + self.meetnet +":" + d) + raise LmwCmdWarn(ti, d) return (d[2:-1]) def cmd(self, process, location, parameter, time_delta, day, @@ -170,12 +232,12 @@ Returns: self.send(cmdstr) d = self.recv() if (d[0] != '!'): - raise LmwCmdWarn(d) + raise LmwCmdWarn(cmdstr, d) return (d[2:-1]) def value(self, process, location, parameter, day = None, time_of_day = None): - """value(process, location, parameter, [day], [time_of_day], [cmd_type="DATA"]): + """value(process, location, parameter, [day], [time_of_day]): Parameters: process: @@ -215,9 +277,33 @@ Returns a single string value or None Logs of """ self.send("LO\r") + self.closesocket() + + +class LmwSipConnectError(Exception): + """Connection exceptions for LmwSip""" + + def __init__(self, message): + self.message = message + + def __str__(self): + return(self.message) class LmwLoginFailure(Exception): """Exception from LmwSip on login failure""" + def __init__(self, user, message): + self.user = user + self.message = message + + def __str__(self): + return("Login with user %s failed: %s", self.user, self.message) + class LmwCmdWarn(Warning): """Exception fro LmwSip on a cmd""" + def __init__(self, cmd, message): + self.cmd = cmd + self.message = message + + def __str__(self): + return("Cmd %s failed: %s", self.cmd, self.message) diff --git a/siprun b/siprun index f25b1d4..c5fe4a1 100755 --- a/siprun +++ b/siprun @@ -46,7 +46,11 @@ def main(): print("Set host and port") usage() sys.exit(3) - lmwsip = LmwSip(ssl=ssl, host=host, port=port) + try: + lmwsip = LmwSip(ssl=ssl, host=host, port=port) + except Exception as e: + print("Connect to lmw failed: %s" % e) + exit(1) if (date == None or time == None): # We assume a 10 minut interval so we use H10 r = lmwsip.lasttime("H10") @@ -61,8 +65,11 @@ def main(): cmd = cmd.replace('{TIME}', time) cmd = cmd.replace('\n', '\r') print("> [%s]" % (cmd.strip('\r'))) - lmwsip.send(cmd) - print("< [%s]" % (lmwsip.recv().strip('\r'))) + try: + lmwsip.send(cmd) + print("< [%s]" % (lmwsip.recv().strip('\r'))) + except: + pass f.close() if __name__ == "__main__":