Compare commits
1 Commits
PythonModu
...
clearbuf
Author | SHA1 | Date | |
---|---|---|---|
2ed0f86fd4 |
13
.drone.yml
13
.drone.yml
@@ -1,13 +0,0 @@
|
|||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: exec
|
|
||||||
name: default
|
|
||||||
|
|
||||||
platform:
|
|
||||||
os: linux
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Run unit test
|
|
||||||
commands:
|
|
||||||
- python -m unittest lmwsip
|
|
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,8 +1,3 @@
|
|||||||
*.pyc
|
|
||||||
*.sip
|
|
||||||
tmp
|
|
||||||
__pycache__
|
__pycache__
|
||||||
build
|
lmwsip-test
|
||||||
dist
|
*.sip
|
||||||
lmwsip_marceln.egg-info
|
|
||||||
test/__pycache__
|
|
||||||
|
39
README.md
39
README.md
@@ -34,41 +34,16 @@ Otherwise the connection fails.
|
|||||||
|
|
||||||
### Library
|
### Library
|
||||||
|
|
||||||
#### Use send (low level)
|
|
||||||
|
|
||||||
``` python
|
``` python
|
||||||
from lmwsip import LmwSip
|
from lmwsip import LmwSip
|
||||||
|
|
||||||
sip = LmwSip(ssl=True, host="sip-lmw.rws.nl", port=443)
|
lmwsip = LmwSip(ssl=True, host="sip-lmw.ad.rws.nl", port=443)
|
||||||
sip.send("LI user,pass\r")
|
lmwsip.send("LI user,pass\r")
|
||||||
print("< [%s]" % (sip.recv().strip('\r')))
|
print("< [%s]" % (lmwsip.recv().strip('\r')))
|
||||||
sip.send("TI LMW\r")
|
lmwsip.send("TI LMW\r")
|
||||||
print("< [%s]" % (sip.recv().strip('\r')))
|
print("< [%s]" % (lmwsip.recv().strip('\r')))
|
||||||
sip.send("LO\r")
|
lmwsip.send("LO\r")
|
||||||
print("< [%s]" % (sip.recv().strip('\r')))
|
print("< [%s]" % (lmwsip.recv().strip('\r')))
|
||||||
```
|
|
||||||
|
|
||||||
#### Use value
|
|
||||||
|
|
||||||
``` python
|
|
||||||
from lmwsip import LmwSip
|
|
||||||
sip = LmwSip("USER", "PASS")
|
|
||||||
print(sip.ti())
|
|
||||||
print(sip.value("WN", "HOEK", "H10"))
|
|
||||||
sip.logout()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Use timeseries
|
|
||||||
``` python
|
|
||||||
from lmwsip import LmwSip
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from pprint import pprint
|
|
||||||
|
|
||||||
end = datetime.now()
|
|
||||||
start = end - timedelta(hours=1)
|
|
||||||
|
|
||||||
sip = LmwSip("USER", "PASS")
|
|
||||||
pprint(sip.timeSerie("WN", "HOEK", "H10", start, end).ts)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### siprun
|
### siprun
|
||||||
|
@@ -1,30 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
from lmwsip import LmwSip
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from pprint import pprint
|
|
||||||
|
|
||||||
def printLocPar(sip, proces, loc, par, start, end):
|
|
||||||
try:
|
|
||||||
r = sip.timeSerie(proces, loc, par, start, end)
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
print("\n%s %s %s:\n" % (proces, loc, par))
|
|
||||||
pprint(r.ts)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
end = datetime.now() + timedelta(minutes=10)
|
|
||||||
start = end - timedelta(hours=1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
sip = LmwSip("<user>", "<pass>")
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
printLocPar(sip, "WN", "HOEK", "H10", start, end)
|
|
||||||
printLocPar(sip, "WN", "LEG1", "Czz10", start, end)
|
|
||||||
printLocPar(sip, "VW", "HOEK", "H10V", start, end)
|
|
||||||
printLocPar(sip, "AS", "HOEK", "H10A", start, end)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
326
lmwsip.py
Normal file
326
lmwsip.py
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
"""Module to support the LmwSip class
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
This class iplement connection to the Rijkswaterstaat Meetnet
|
||||||
|
Water (LMW) with the Standard Interface Protocol using the
|
||||||
|
Rijkswaterstaat Meetnet Infrastructuur (RMI).
|
||||||
|
|
||||||
|
https://waterberichtgeving.rws.nl/water-en-weer/metingen
|
||||||
|
|
||||||
|
Support for:
|
||||||
|
ti
|
||||||
|
cmd(wn, vw, as)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, user=None, password=None,
|
||||||
|
host="sip-lmw.rws.nl", port=443, meetnet="LMW", ssl = True,
|
||||||
|
check_ssl = True, timeout = 10, log = None, clearbuf = False):
|
||||||
|
"""LmwSip(user, password, [host], [port], [meetnet], [ssl], [check_ssl], [timeout], [log])
|
||||||
|
|
||||||
|
user(optinal): Lmw user name
|
||||||
|
password(optional): Lmw password
|
||||||
|
host(optional): Default sip-lmw.rws.nl
|
||||||
|
port(optional): Default 443
|
||||||
|
meetnet(optional): Default LMW
|
||||||
|
ssl(optional): Default true
|
||||||
|
check_ssl(optional): true
|
||||||
|
timeout(optional): 10
|
||||||
|
log(optional): None
|
||||||
|
clearbuf(optinal): None
|
||||||
|
|
||||||
|
Opens the connection and logs in
|
||||||
|
"""
|
||||||
|
self.user = user
|
||||||
|
self.password = password
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.meetnet = meetnet
|
||||||
|
self.ssl = ssl
|
||||||
|
self.check_ssl = check_ssl
|
||||||
|
self.timeout = timeout
|
||||||
|
self.clearbuf = clearbuf
|
||||||
|
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):
|
||||||
|
self.login()
|
||||||
|
|
||||||
|
def lasttime(self, parameter):
|
||||||
|
#
|
||||||
|
# Find the last valid 10 minute window.
|
||||||
|
# The measurement of 12:00 is avaiable at 12:05:30.
|
||||||
|
# Before 12:05:30 we should use 11:50:00.
|
||||||
|
#
|
||||||
|
# At 12:05:29 we substract 15:29 from the time!
|
||||||
|
#
|
||||||
|
# Also note that we use GMT. So we should add one hour
|
||||||
|
# because we use GMT +1 (MET, UTC-1)
|
||||||
|
#
|
||||||
|
if (parameter.find("10") != -1):
|
||||||
|
now=time.time()
|
||||||
|
dt = now%600
|
||||||
|
if (dt < 330):
|
||||||
|
now = 3000 + now - dt
|
||||||
|
else:
|
||||||
|
now = 3600 + now - dt
|
||||||
|
else:
|
||||||
|
#
|
||||||
|
# e.g. H1 use 30 seconds to calculate the time.
|
||||||
|
#
|
||||||
|
dt = now%600
|
||||||
|
if (dt < 30):
|
||||||
|
now = 3540 + now - dt
|
||||||
|
else:
|
||||||
|
now = 3600 + now - dt
|
||||||
|
time_of_day=time.strftime("%H:%M", time.gmtime(now))
|
||||||
|
return { "day": time.strftime("%d-%m-%Y", time.gmtime(now)),
|
||||||
|
"time_of_day": time.strftime("%H:%M", time.gmtime(now)) }
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
"""connect()
|
||||||
|
|
||||||
|
connects to lmw with tcp using the values of the object creation.
|
||||||
|
"""
|
||||||
|
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):
|
||||||
|
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
|
||||||
|
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 emptysocket(self):
|
||||||
|
"""emptysocket()
|
||||||
|
|
||||||
|
If clearbuf read all the data from the socket and ignore it.
|
||||||
|
"""
|
||||||
|
if self._socket != None and self.clearbuf:
|
||||||
|
try:
|
||||||
|
self._socket.settimeout(0)
|
||||||
|
b = self._socket.recv(4096)
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
self._socket.settimeout(self.timeout)
|
||||||
|
|
||||||
|
def send(self, sipcmd):
|
||||||
|
"""send(sipcmd)
|
||||||
|
|
||||||
|
send a sip command to the server
|
||||||
|
"""
|
||||||
|
if self._socket != None:
|
||||||
|
try:
|
||||||
|
logcmd = sipcmd.strip('\r')
|
||||||
|
if re.match("^LI", logcmd, re.IGNORECASE):
|
||||||
|
logcmd = re.sub(",.*", ", ******", logcmd)
|
||||||
|
self.log.debug("LmwSip.send(%s)" % logcmd)
|
||||||
|
self.emptysocket()
|
||||||
|
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()
|
||||||
|
|
||||||
|
recieve a answer from the sip server
|
||||||
|
"""
|
||||||
|
buf=""
|
||||||
|
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.strip('\r'))
|
||||||
|
else:
|
||||||
|
self.log.debug("LmwSip.recv: result: %s" % buf.strip('\r'))
|
||||||
|
return(buf)
|
||||||
|
|
||||||
|
def login(self):
|
||||||
|
"""login()
|
||||||
|
|
||||||
|
Login lmw using the object creation user, password.
|
||||||
|
Raises a LmwLoginFailure exception on failure
|
||||||
|
"""
|
||||||
|
li="LI " + self.user + "," + self.password + "\r"
|
||||||
|
self.send(li)
|
||||||
|
d = self.recv()
|
||||||
|
if (d[0] != '!'):
|
||||||
|
raise LmwLoginFailure(self.user + ":" + d)
|
||||||
|
|
||||||
|
def ti(self):
|
||||||
|
"""ti()
|
||||||
|
|
||||||
|
Request the time from lmw and returns the string.
|
||||||
|
|
||||||
|
Raises a LmwCmdWarn of failure
|
||||||
|
"""
|
||||||
|
ti="TI " + self.meetnet + "\r"
|
||||||
|
self.send(ti)
|
||||||
|
d = self.recv()
|
||||||
|
return (d[2:-1])
|
||||||
|
|
||||||
|
def cmd(self, process, location, parameter, time_delta, day,
|
||||||
|
time_of_day, cmd_type="DATA"):
|
||||||
|
"""cmd(process, location, parameter, time_delta, day, time_of_day)
|
||||||
|
|
||||||
|
Send a cmd to LMW and returns the lmw string
|
||||||
|
|
||||||
|
process: <WN|VW|AS>
|
||||||
|
location: <lmw location (e.g. HOEK)>
|
||||||
|
parameter: <lmw parameter (e.g. H10)>
|
||||||
|
time_delta: <Time windows (max 23:59, e.g. +01:00>
|
||||||
|
day: <Date>
|
||||||
|
time_of_day: <Time>
|
||||||
|
cmd_type: [DATA|DATB|OORS|OORB|""]
|
||||||
|
|
||||||
|
Example:
|
||||||
|
lmw.cmd("WN", "HOEK", "H10", "+01:00", "13-08-2018", "16:00")
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The LMW answer string
|
||||||
|
"""
|
||||||
|
if (process == "AS"):
|
||||||
|
data=""
|
||||||
|
else:
|
||||||
|
data="," + cmd_type
|
||||||
|
|
||||||
|
cmdstr=process + " " + self.meetnet + "," + location + "," + \
|
||||||
|
parameter + "," + time_delta + "," + day + "," + \
|
||||||
|
time_of_day + data + "\r"
|
||||||
|
|
||||||
|
self.send(cmdstr)
|
||||||
|
d = self.recv()
|
||||||
|
if (d[0] != '!'):
|
||||||
|
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]):
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
process: <WN|VW|AS>
|
||||||
|
location: <lmw location (e.g. HOEK)>
|
||||||
|
parameter: <lmw parameter (e.g. H10)>
|
||||||
|
day: [date = now()]
|
||||||
|
time_of_day: [time = now()]
|
||||||
|
|
||||||
|
The default returns the last value.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
lmw.data_string("WN", "HOEK", "H10")
|
||||||
|
|
||||||
|
Returns a single string value or None
|
||||||
|
"""
|
||||||
|
if (day == None or time_of_day == None):
|
||||||
|
last = self.lasttime(parameter)
|
||||||
|
if (day==None):
|
||||||
|
day=last["day"]
|
||||||
|
if (time_of_day==None):
|
||||||
|
time_of_day=last["time_of_day"]
|
||||||
|
res = self.cmd(process, location, parameter, "+00:00", day,
|
||||||
|
time_of_day, "DATA")
|
||||||
|
value=re.sub("/.*$", "", res)
|
||||||
|
if (value == "99999"):
|
||||||
|
value=""
|
||||||
|
elif (value == "-999999999"):
|
||||||
|
value=""
|
||||||
|
#
|
||||||
|
# We should check the "kwaliteit"
|
||||||
|
#
|
||||||
|
return(value)
|
||||||
|
|
||||||
|
def logout(self):
|
||||||
|
"""logout()
|
||||||
|
|
||||||
|
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)
|
@@ -1,511 +0,0 @@
|
|||||||
"""Module to support the LmwSip class
|
|
||||||
|
|
||||||
See: LmwSip"""
|
|
||||||
|
|
||||||
import socket
|
|
||||||
import ssl
|
|
||||||
import select
|
|
||||||
import time
|
|
||||||
import re
|
|
||||||
import logging
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from dateutil import tz
|
|
||||||
|
|
||||||
class LmwSip:
|
|
||||||
"""Class to connect to the LMW Standard Interface prototcol (sip)
|
|
||||||
|
|
||||||
This class iplement connection to the Rijkswaterstaat Meetnet
|
|
||||||
Water (LMW) with the Standard Interface Protocol using the
|
|
||||||
Rijkswaterstaat Meetnet Infrastructuur (RMI).
|
|
||||||
|
|
||||||
https://waterberichtgeving.rws.nl/water-en-weer/metingen
|
|
||||||
|
|
||||||
Support for:
|
|
||||||
ti
|
|
||||||
cmd(wn, vw, as)
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, user=None, password=None,
|
|
||||||
host="sip-lmw.rws.nl", port=443, meetnet="LMW", ssl = True,
|
|
||||||
check_ssl = True, timeout = 10, log = None, cleartelnet = False,
|
|
||||||
reconnecttime=540):
|
|
||||||
"""LmwSip(user, password, [host], [port], [meetnet], [ssl], [check_ssl], [timeout], [log])
|
|
||||||
|
|
||||||
user(optinal): Lmw user name
|
|
||||||
password(optional): Lmw password
|
|
||||||
host(optional): Default sip-lmw.rws.nl
|
|
||||||
port(optional): Default 443
|
|
||||||
meetnet(optional): Default LMW
|
|
||||||
ssl(optional): Default true
|
|
||||||
check_ssl(optional): Default true
|
|
||||||
timeout(optional): Default 10
|
|
||||||
log(optional): Default None
|
|
||||||
cleartelnet(optional): Default False
|
|
||||||
reconnecttime(optional): Default 540
|
|
||||||
|
|
||||||
Opens the connection and logs in.
|
|
||||||
"""
|
|
||||||
self.user = user
|
|
||||||
self.password = password
|
|
||||||
self.host = host
|
|
||||||
self.port = port
|
|
||||||
self.meetnet = meetnet
|
|
||||||
self.ssl = ssl
|
|
||||||
self.check_ssl = check_ssl
|
|
||||||
self.timeout = timeout
|
|
||||||
self.cleartelnet = cleartelnet
|
|
||||||
self.reconnecttime = reconnecttime
|
|
||||||
self._connecttime = time.time()
|
|
||||||
self._socket = None
|
|
||||||
if (log != None):
|
|
||||||
self.log = log
|
|
||||||
self.log.debug("LmwSip.init(%s, **********, %s, %s, %s, %s, %s, %s, %s, %s)" %
|
|
||||||
(user, host, port, meetnet, ssl, check_ssl, timeout, cleartelnet, reconnecttime))
|
|
||||||
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):
|
|
||||||
self.login()
|
|
||||||
else:
|
|
||||||
self.reconnecttime = 0
|
|
||||||
|
|
||||||
def lasttime(self, parameter):
|
|
||||||
#
|
|
||||||
# Find the last valid 10 minute window.
|
|
||||||
# The measurement of 12:00 is avaiable at 12:05:30.
|
|
||||||
# Before 12:05:30 we should use 11:50:00.
|
|
||||||
#
|
|
||||||
# At 12:05:29 we substract 15:29 from the time!
|
|
||||||
#
|
|
||||||
# Also note that we use GMT. So we should add one hour
|
|
||||||
# because we use GMT +1 (MET, UTC-1)
|
|
||||||
#
|
|
||||||
if (parameter.find("10") != -1):
|
|
||||||
now=time.time()
|
|
||||||
dt = now%600
|
|
||||||
if (dt < 330):
|
|
||||||
now = 3000 + now - dt
|
|
||||||
else:
|
|
||||||
now = 3600 + now - dt
|
|
||||||
else:
|
|
||||||
#
|
|
||||||
# e.g. H1 use 30 seconds to calculate the time.
|
|
||||||
#
|
|
||||||
dt = now%600
|
|
||||||
if (dt < 30):
|
|
||||||
now = 3540 + now - dt
|
|
||||||
else:
|
|
||||||
now = 3600 + now - dt
|
|
||||||
time_of_day=time.strftime("%H:%M", time.gmtime(now))
|
|
||||||
return { "day": time.strftime("%d-%m-%Y", time.gmtime(now)),
|
|
||||||
"time_of_day": time.strftime("%H:%M", time.gmtime(now)) }
|
|
||||||
|
|
||||||
def connect(self):
|
|
||||||
"""connect()
|
|
||||||
|
|
||||||
connects to lmw with tcp using the values of the object creation.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self._tcp = socket.create_connection((self.host, self.port))
|
|
||||||
self._connecttime = time.time()
|
|
||||||
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):
|
|
||||||
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
|
|
||||||
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 reconnectcheck(self):
|
|
||||||
"""Checks if the connection is longer open than the reconnect time.
|
|
||||||
After this time a logout is sent and a new connection is created.
|
|
||||||
|
|
||||||
This prevents the 10 minute server timeout"""
|
|
||||||
if self.reconnecttime > 0:
|
|
||||||
ct = time.time() - self._connecttime
|
|
||||||
if ct > self.reconnecttime:
|
|
||||||
self.log.debug("LmwSip.reconnectcheck: reconnect after %i seconds" % ct)
|
|
||||||
#
|
|
||||||
# Disable check for the reconnect
|
|
||||||
#
|
|
||||||
self.reconnecttime = - self.reconnecttime
|
|
||||||
self.logout()
|
|
||||||
time.sleep(1)
|
|
||||||
self.connect()
|
|
||||||
self.login()
|
|
||||||
self.reconnecttime = - self.reconnecttime
|
|
||||||
|
|
||||||
def send(self, sipcmd):
|
|
||||||
"""send(sipcmd)
|
|
||||||
|
|
||||||
send a sip command to the server
|
|
||||||
"""
|
|
||||||
self.reconnectcheck()
|
|
||||||
if self._socket != None:
|
|
||||||
try:
|
|
||||||
logcmd = sipcmd.strip('\r')
|
|
||||||
if re.match("^LI", logcmd, re.IGNORECASE):
|
|
||||||
logcmd = re.sub(",.*", ", ******", logcmd)
|
|
||||||
self.log.debug("LmwSip.send(%s)" % logcmd)
|
|
||||||
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.warning("LmwSip.send: No connection")
|
|
||||||
|
|
||||||
def telnetheader(self, header):
|
|
||||||
a = b'\xff\xfd\x01\xff\xfd\x03\xff\xfd\x00\xff\xfc\x01\xff\xfb\x00'
|
|
||||||
self.log.debug("LmwSip.telnetheader(%s) --> %s" % (header, a))
|
|
||||||
try:
|
|
||||||
self._socket.sendall(a)
|
|
||||||
except Exception as e:
|
|
||||||
self.log.error("LmwSip.telnetheader(%s) --> %s failed: %s" % (header, a, e))
|
|
||||||
self.closesocket()
|
|
||||||
raise LmwSipConnectError("LmwSip.telnetheader: Socket connection lost")
|
|
||||||
|
|
||||||
def recv(self):
|
|
||||||
"""recv()
|
|
||||||
|
|
||||||
recieve a answer from the sip server
|
|
||||||
"""
|
|
||||||
bytebuf=b''
|
|
||||||
stringbuf=""
|
|
||||||
while (self._socket != None) and (stringbuf.find("\r") == -1):
|
|
||||||
try:
|
|
||||||
self.log.debug("LmwSip.recv: %s: Waiting for data" % self.cleartelnet);
|
|
||||||
bytebuf = self._socket.recv(4096)
|
|
||||||
self.log.debug("recv: bytebuf: %s" % bytebuf)
|
|
||||||
if self.cleartelnet:
|
|
||||||
if bytebuf[0] == 255:
|
|
||||||
bytebuf = b''
|
|
||||||
except Exception as e:
|
|
||||||
self.log.error("SipLmw.recv: socket timeout: %s", e)
|
|
||||||
self.closesocket()
|
|
||||||
raise LmwSipConnectError("LmwSip.recv: No data recieved")
|
|
||||||
try:
|
|
||||||
stringbuf += bytebuf.decode('utf-8')
|
|
||||||
self.log.debug("recv: stringbuf: %s" % stringbuf)
|
|
||||||
except Exception as e:
|
|
||||||
self.log.error("SipLmw.recv: decode error: %s", e)
|
|
||||||
self.closesocket()
|
|
||||||
raise LmwSipDecodeError("LmwSip.recv: decode error", bytebuf)
|
|
||||||
if self._socket == None:
|
|
||||||
self.log.warn("LmwSip.recv: No connection")
|
|
||||||
elif len(stringbuf) == 0:
|
|
||||||
self.log.warn("LmwSip.recv: No data")
|
|
||||||
elif stringbuf[0] != '!':
|
|
||||||
self.log.warn("LmwSip.recv: Sip error: %s" % stringbuf.strip('\r'))
|
|
||||||
else:
|
|
||||||
self.log.debug("LmwSip.recv: result: %s" % stringbuf.strip('\r'))
|
|
||||||
return(stringbuf)
|
|
||||||
|
|
||||||
def login(self):
|
|
||||||
"""login()
|
|
||||||
|
|
||||||
Login lmw using the object creation user, password.
|
|
||||||
Raises a LmwLoginFailure exception on failure
|
|
||||||
"""
|
|
||||||
li="LI " + self.user + "," + self.password + "\r"
|
|
||||||
self.send(li)
|
|
||||||
d = self.recv()
|
|
||||||
if (d[0] != '!'):
|
|
||||||
raise LmwLoginFailure(self.user + ":" + d)
|
|
||||||
|
|
||||||
def ti(self):
|
|
||||||
"""ti()
|
|
||||||
|
|
||||||
Request the time from lmw and returns the string.
|
|
||||||
|
|
||||||
Raises a LmwCmdWarn of failure
|
|
||||||
"""
|
|
||||||
ti="TI " + self.meetnet + "\r"
|
|
||||||
self.send(ti)
|
|
||||||
d = self.recv()
|
|
||||||
return (d[2:-1])
|
|
||||||
|
|
||||||
def cmd(self, process, location, parameter, time_delta, day,
|
|
||||||
time_of_day, cmd_type="DATA"):
|
|
||||||
"""cmd(process, location, parameter, time_delta, day, time_of_day)
|
|
||||||
|
|
||||||
Send a cmd to LMW and returns the lmw string
|
|
||||||
|
|
||||||
process: <WN|VW|AS>
|
|
||||||
location: <lmw location (e.g. HOEK)>
|
|
||||||
parameter: <lmw parameter (e.g. H10)>
|
|
||||||
time_delta: <Time windows (max 23:59, e.g. +01:00>
|
|
||||||
day: <Date>
|
|
||||||
time_of_day: <Time>
|
|
||||||
cmd_type: [DATA|DATB|OORS|OORB|""]
|
|
||||||
|
|
||||||
Example:
|
|
||||||
lmw.cmd("WN", "HOEK", "H10", "+01:00", "13-08-2018", "16:00")
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The LMW answer string
|
|
||||||
"""
|
|
||||||
if (process == "AS"):
|
|
||||||
data=""
|
|
||||||
else:
|
|
||||||
data="," + cmd_type
|
|
||||||
|
|
||||||
cmdstr=process + " " + self.meetnet + "," + location + "," + \
|
|
||||||
parameter + "," + time_delta + "," + day + "," + \
|
|
||||||
time_of_day + data + "\r"
|
|
||||||
|
|
||||||
self.send(cmdstr)
|
|
||||||
d = self.recv()
|
|
||||||
if (d[0] != '!'):
|
|
||||||
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]):
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
process: <WN|VW|AS>
|
|
||||||
location: <lmw location (e.g. HOEK)>
|
|
||||||
parameter: <lmw parameter (e.g. H10)>
|
|
||||||
day: [date = now()]
|
|
||||||
time_of_day: [time = now()]
|
|
||||||
|
|
||||||
The default returns the last value.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
lmw.data_string("WN", "HOEK", "H10")
|
|
||||||
|
|
||||||
Returns a single string value or None
|
|
||||||
"""
|
|
||||||
if (day == None or time_of_day == None):
|
|
||||||
last = self.lasttime(parameter)
|
|
||||||
if (day==None):
|
|
||||||
day=last["day"]
|
|
||||||
if (time_of_day==None):
|
|
||||||
time_of_day=last["time_of_day"]
|
|
||||||
res = self.cmd(process, location, parameter, "+00:00", day,
|
|
||||||
time_of_day, "DATA")
|
|
||||||
value=re.sub("/.*$", "", res)
|
|
||||||
if (value == "99999"):
|
|
||||||
value=""
|
|
||||||
elif (value == "-999999999"):
|
|
||||||
value=""
|
|
||||||
#
|
|
||||||
# We should check the "kwaliteit"
|
|
||||||
#
|
|
||||||
return(value)
|
|
||||||
|
|
||||||
def _lmwdelta_(self, window):
|
|
||||||
h = 24*window.days + window.seconds // 3600
|
|
||||||
m = (window.seconds % 3600)//60
|
|
||||||
return("+%02i:%02i" % (h, m))
|
|
||||||
|
|
||||||
def _roundtime_(self, time, parameter):
|
|
||||||
if time.microsecond != 0:
|
|
||||||
time += timedelta(microseconds=1000000-time.microsecond)
|
|
||||||
if time.second != 0:
|
|
||||||
time += timedelta(seconds=60-time.second)
|
|
||||||
if (parameter.find("10") != -1) and (time.minute % 10 != 0):
|
|
||||||
time += timedelta(minutes=(10-time.minute%10))
|
|
||||||
return(time)
|
|
||||||
|
|
||||||
def timeSerie(self, process, location, parameter,
|
|
||||||
startTime, endTime, cmd_type="DATB"):
|
|
||||||
"""timeSerie(process, location, parameter, startTime, endTime, cmd_type="DATA")
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
process: <WN|VW|AS>
|
|
||||||
location: <lmw location (e.g. HOEK)>
|
|
||||||
parameter: <lmw parameter (e.g. H10)>
|
|
||||||
startTime: Start time (datetime)
|
|
||||||
endTime: End time (datetime)
|
|
||||||
cmd_type: [DATA|DATB]
|
|
||||||
|
|
||||||
startTime is rounded up to the next measurement time.
|
|
||||||
So 12:00:00.000001 --> 12:00:10.00.0
|
|
||||||
|
|
||||||
The times should have correct timezone information. Otherwise local timezone
|
|
||||||
is assumed. Timezones are converted to 'GMT+1' for the sip commands.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
lmw.data_string("WN", "HOEK", "H10", ...)
|
|
||||||
|
|
||||||
Returns a LmwtimeSerie object
|
|
||||||
|
|
||||||
Errors:
|
|
||||||
startTime > endTime
|
|
||||||
endTime - startTime > 24 hour
|
|
||||||
now - startTime < 30 days
|
|
||||||
"""
|
|
||||||
startTime = self._roundtime_(startTime.astimezone(tz.gettz('GMT+1')), parameter)
|
|
||||||
endTime = endTime.astimezone(tz.gettz('GMT+1'))
|
|
||||||
|
|
||||||
if (parameter.find("10") != -1):
|
|
||||||
delta = timedelta(minutes=10)
|
|
||||||
else:
|
|
||||||
delta = timedelta(minutes=1)
|
|
||||||
|
|
||||||
if startTime > endTime:
|
|
||||||
self.log.warn("starttime > endtime: %s > %s", startTime, endTime)
|
|
||||||
raise sipTimeSeriesError(startTime, endTime,
|
|
||||||
"starttime > endtime")
|
|
||||||
|
|
||||||
if datetime.now(tz=tz.gettz('GMT+1')) - startTime > timedelta(days=30):
|
|
||||||
self.log.warn("now() - starttime > 30 days: %s", startTime)
|
|
||||||
raise sipTimeSeriesError(startTime, endTime,
|
|
||||||
"now - starttime > 30 days")
|
|
||||||
|
|
||||||
self.log.debug("LmwSip.timeSerie: startTime: %s" % startTime)
|
|
||||||
self.log.debug("LmwSip.timeSerie: endTime: %s" % endTime)
|
|
||||||
|
|
||||||
if process == "VW":
|
|
||||||
cmd_type="DATA"
|
|
||||||
|
|
||||||
res = lmwTimeSerie(startTime, delta, "")
|
|
||||||
|
|
||||||
while startTime <= endTime:
|
|
||||||
if endTime - startTime > timedelta(days=1):
|
|
||||||
window = timedelta(days=1) - delta
|
|
||||||
else:
|
|
||||||
window = endTime-startTime
|
|
||||||
values = self.cmd(process, location, parameter,
|
|
||||||
self._lmwdelta_(window),
|
|
||||||
startTime.strftime("%d-%m-%Y"),
|
|
||||||
startTime.strftime("%H:%M"),
|
|
||||||
cmd_type)
|
|
||||||
res.addvalues(startTime, values)
|
|
||||||
startTime += window + delta
|
|
||||||
|
|
||||||
return(res)
|
|
||||||
|
|
||||||
def logout(self):
|
|
||||||
"""logout()
|
|
||||||
|
|
||||||
Logs of
|
|
||||||
"""
|
|
||||||
self.send("LO\r")
|
|
||||||
self.closesocket()
|
|
||||||
|
|
||||||
class lmwTimeSerie:
|
|
||||||
"""Class for lmw results.
|
|
||||||
|
|
||||||
The result are in lmwTimeSerie.ts as array
|
|
||||||
|
|
||||||
[ <time1>, [<value1 a, value1 b, ...], kwaliteit1, additionele kwaliteit1],
|
|
||||||
[ <time2>, [<value2 a, value2 b, ...], kwaliteit2, additionele kwaliteit2],
|
|
||||||
...
|
|
||||||
|
|
||||||
Note:
|
|
||||||
* For most measurements there is only one value (e.g H10).
|
|
||||||
* Additionale kwaliteit is optional and may contain None.
|
|
||||||
* Result times in UTC
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, start, delta, values=""):
|
|
||||||
"""lmwTimeSerie(start, delta, values)
|
|
||||||
|
|
||||||
Create a lmwTimeSerie object with:
|
|
||||||
start: Start time
|
|
||||||
delta: Period of the measurements
|
|
||||||
values: lmw result string
|
|
||||||
"""
|
|
||||||
self.ts = []
|
|
||||||
self.delta = delta
|
|
||||||
if values != "":
|
|
||||||
self.addvalues(start, values)
|
|
||||||
|
|
||||||
def addvalues(self, start, values):
|
|
||||||
"""addvalues(start, delta, values)
|
|
||||||
|
|
||||||
Add values to a timeserie
|
|
||||||
start: Start time
|
|
||||||
delta: Period of the measurements
|
|
||||||
values: lmw result string
|
|
||||||
|
|
||||||
"""
|
|
||||||
start = start.astimezone(tz.gettz('UTC'))
|
|
||||||
for e in values.split(";"):
|
|
||||||
v = e.split("/")
|
|
||||||
v[0] = v[0].split(",")
|
|
||||||
if len(v) == 2:
|
|
||||||
v.append(None)
|
|
||||||
self.ts.append([start, v[0], v[1], v[2]])
|
|
||||||
start += self.delta
|
|
||||||
|
|
||||||
class sipTimeSeriesError(Exception):
|
|
||||||
"""Parameter errors for timeSeries"""
|
|
||||||
def __init__(self, startTime, endTime, message):
|
|
||||||
self.startTime = startTime
|
|
||||||
self.endTime = endTime
|
|
||||||
self.message = message
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return("%s\n starttime: %s\n end time: %s" %
|
|
||||||
(self.message, self.startTime, self.endTime))
|
|
||||||
|
|
||||||
class LmwSipConnectError(Exception):
|
|
||||||
"""Connection exceptions for LmwSip"""
|
|
||||||
|
|
||||||
def __init__(self, message):
|
|
||||||
self.message = message
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return(self.message)
|
|
||||||
|
|
||||||
class LmwSipDecodeError(Exception):
|
|
||||||
"""Connection exceptions for LmwSip"""
|
|
||||||
|
|
||||||
def __init__(self, message, buf):
|
|
||||||
self.message = message
|
|
||||||
self.buf = buf
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return(self.message + ":" + buf)
|
|
||||||
|
|
||||||
|
|
||||||
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.replace('\r', '')
|
|
||||||
self.message = message
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return("Cmd %s failed: %s" %(self.cmd, self.message))
|
|
22
setup.py
22
setup.py
@@ -1,22 +0,0 @@
|
|||||||
import setuptools
|
|
||||||
|
|
||||||
with open("README.md", "r") as fh:
|
|
||||||
long_description = fh.read()
|
|
||||||
|
|
||||||
setuptools.setup(
|
|
||||||
name="lmwsip-marceln", # Replace with your own username
|
|
||||||
version="0.0.1",
|
|
||||||
author="Marcel Nijenhof",
|
|
||||||
author_email="pip@pion.xs4all.nl",
|
|
||||||
description="Interface for the lmw sip protocol",
|
|
||||||
long_description=long_description,
|
|
||||||
long_description_content_type="text/markdown",
|
|
||||||
url="https://marceln.org/git/Werk/lmwsip",
|
|
||||||
packages=setuptools.find_packages(),
|
|
||||||
classifiers=[
|
|
||||||
"Programming Language :: Python :: 3",
|
|
||||||
"License :: TODO",
|
|
||||||
"Operating System :: OS Independent",
|
|
||||||
],
|
|
||||||
python_requires='>=3.6',
|
|
||||||
)
|
|
97
siprun
97
siprun
@@ -2,49 +2,74 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import getopt
|
import getopt
|
||||||
import argparse
|
|
||||||
from lmwsip import LmwSip
|
from lmwsip import LmwSip
|
||||||
|
|
||||||
def main():
|
def usage():
|
||||||
lastTime=LmwSip.lasttime(None, "H10")
|
print("siprun [-H] [-s] [-d <date>] [-t <time>] [-h <host>] [-p <port>] [<files>]")
|
||||||
parser = argparse.ArgumentParser(description="Run a sip file.")
|
print("\t-H: Show usage")
|
||||||
parser.add_argument("-u", "--unencrypted", action="store_true",
|
print("\t-s: SSL connection")
|
||||||
help="Run a sip connection without ssl")
|
print("\t-d <date>: Date replacement string (2019-02-14)")
|
||||||
parser.add_argument("-c", "--cleartelnet", action="store_true",
|
print("\t-t <time>: Time replacement string (17:00)")
|
||||||
help="Clear telnet protocol in tcp session")
|
print("\t-h <host>: Connect to host")
|
||||||
parser.add_argument("-H", "--host", action='store',
|
print("\t-p <port>: Connect to port")
|
||||||
default="sip-lmw.rws.nl",
|
print("\t-<files>: LMW commando files")
|
||||||
help="Host to connect to")
|
|
||||||
parser.add_argument("-p", "--port", action='store', type=int, default=443,
|
|
||||||
help="Port to connect to")
|
|
||||||
parser.add_argument("-d", "--date", action='store',
|
|
||||||
default=lastTime["day"],
|
|
||||||
help="Date replacement string [DD-MM-YYYY]")
|
|
||||||
parser.add_argument("-t", "--time", action='store',
|
|
||||||
default=lastTime["time_of_day"],
|
|
||||||
help="Time replacement string [HH:MM]")
|
|
||||||
parser.add_argument("files", type=argparse.FileType('r'), nargs="+",
|
|
||||||
help="Sip files to run")
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
|
def main():
|
||||||
try:
|
try:
|
||||||
lmwsip = LmwSip(host=args.host, port=args.port,
|
opts, args = getopt.getopt(sys.argv[1:], "sh:p:d:t:", ["help", "output="])
|
||||||
ssl=not args.unencrypted,
|
except getopt.GetoptError as err:
|
||||||
cleartelnet=args.cleartelnet)
|
# print help information and exit:
|
||||||
|
print(err) # will print something like "option -a not recognized"
|
||||||
|
usage()
|
||||||
|
sys.exit(2)
|
||||||
|
ssl=False
|
||||||
|
time=None
|
||||||
|
date=None
|
||||||
|
host=None
|
||||||
|
port=None
|
||||||
|
for o, a in opts:
|
||||||
|
if o == "-H":
|
||||||
|
usage()
|
||||||
|
sys.exit(0)
|
||||||
|
elif o == "-s":
|
||||||
|
ssl=True
|
||||||
|
elif o == "-d":
|
||||||
|
date=a
|
||||||
|
elif o == "-t":
|
||||||
|
time=a
|
||||||
|
elif o == "-h":
|
||||||
|
host=a
|
||||||
|
elif o == "-p":
|
||||||
|
port=a
|
||||||
|
if (host==None or port==None):
|
||||||
|
print("Set host and port")
|
||||||
|
usage()
|
||||||
|
sys.exit(3)
|
||||||
|
try:
|
||||||
|
lmwsip = LmwSip(ssl=ssl, host=host, port=port)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Connect to lmw failed: %s" % e)
|
print("Connect to lmw failed: %s" % e)
|
||||||
exit(1)
|
exit(1)
|
||||||
for f in args.files:
|
if (date == None or time == None):
|
||||||
for cmd in f:
|
# We assume a 10 minut interval so we use H10
|
||||||
cmd = cmd.replace('{DATE}', args.date)
|
r = lmwsip.lasttime("H10")
|
||||||
cmd = cmd.replace('{TIME}', args.time)
|
if (date == None):
|
||||||
cmd = cmd.replace('\n', '\r')
|
date = r["day"]
|
||||||
print("> [%s]" % (cmd.strip('\r')))
|
if (time == None):
|
||||||
try:
|
time = r["time_of_day"]
|
||||||
lmwsip.send(cmd)
|
for cmdfile in args:
|
||||||
print("< [%s]" % (lmwsip.recv().strip('\r')))
|
with open(cmdfile, "r") as f:
|
||||||
except:
|
for cmd in f:
|
||||||
pass
|
cmd = cmd.replace('{DATE}', date)
|
||||||
|
cmd = cmd.replace('{TIME}', time)
|
||||||
|
cmd = cmd.replace('\n', '\r')
|
||||||
|
print("> [%s]" % (cmd.strip('\r')))
|
||||||
|
try:
|
||||||
|
lmwsip.send(cmd)
|
||||||
|
print("< [%s]" % (lmwsip.recv().strip('\r')))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
f.close()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@@ -1,51 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import lmwsip
|
|
||||||
import stubSipServer
|
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from dateutil import tz
|
|
||||||
|
|
||||||
class lmwsipTest(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.sipserver = stubSipServer.sipServer()
|
|
||||||
self.sipserver.run()
|
|
||||||
self.sip = lmwsip.LmwSip("USER", "PASS", "localhost",
|
|
||||||
self.sipserver.port, ssl=False)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.sipserver.kill()
|
|
||||||
self.sip.closesocket()
|
|
||||||
|
|
||||||
def test_sipobj(self):
|
|
||||||
self.assertEqual(type(self.sip), lmwsip.LmwSip)
|
|
||||||
|
|
||||||
def test_ti(self):
|
|
||||||
self.assertEqual(type(self.sip.ti()), str)
|
|
||||||
|
|
||||||
def test_cmd(self):
|
|
||||||
self.assertEqual(type(self.sip.cmd("WN", "DUMMY", "D10", "+00:59", "2020-01-01", "00:00")), str)
|
|
||||||
|
|
||||||
def test_logout(self):
|
|
||||||
self.assertEqual(self.sip.logout(), None)
|
|
||||||
|
|
||||||
def test_lmwTimeSerie(self):
|
|
||||||
timezone = tz.gettz('GMT+1')
|
|
||||||
res = self.sip.timeSerie("WN", "DUMMY", "D10",
|
|
||||||
datetime.now(timezone)-timedelta(minutes=60),
|
|
||||||
datetime.now(timezone))
|
|
||||||
self.assertEqual(type(res.ts), list)
|
|
||||||
self.assertEqual(len(res.ts), 6)
|
|
||||||
self.assertEqual(res.ts[1][1][0], '1')
|
|
||||||
|
|
||||||
def test_roundtime(self):
|
|
||||||
timezone = tz.gettz('GMT+1')
|
|
||||||
t1 = datetime(2020, 1, 1, 0, 10, 0, 0, timezone)
|
|
||||||
t2 = datetime(2020, 1, 1, 0, 0, 0, 1, timezone)
|
|
||||||
self.assertEqual(self.sip._roundtime_(t1, "D10"), t1)
|
|
||||||
self.assertEqual(self.sip._roundtime_(t2, "D10"), t1)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main()
|
|
@@ -1,116 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
"""A stub sipserver for testing lmwsip
|
|
||||||
|
|
||||||
This is a stub sipserver that implements a small subset of the sip
|
|
||||||
protocol to perform unit tests.
|
|
||||||
|
|
||||||
Implements the following commands:
|
|
||||||
|
|
||||||
CMD> LI USER,PASS
|
|
||||||
ANS< !
|
|
||||||
|
|
||||||
CMD> TI LMW
|
|
||||||
ANS< ! 20-JAN-01 00:00:00
|
|
||||||
|
|
||||||
CMD> WN LMW,DUMMY,D10,+HH:MM,yyyy-mm-dd,HH:MM,DATA
|
|
||||||
ANS< ! 1/10,;2/10;....
|
|
||||||
|
|
||||||
CMD> WN LMW,DUMMY,D10,+HH:MM,yyyy-mm-dd,HH:MM,DATB
|
|
||||||
ANS< ! 1/10/0;2/10/0;....
|
|
||||||
|
|
||||||
CMD> LO
|
|
||||||
ANS< !
|
|
||||||
|
|
||||||
All other commands result in a "?"
|
|
||||||
|
|
||||||
CMD> *
|
|
||||||
ANS< ? ERROR
|
|
||||||
|
|
||||||
Note:
|
|
||||||
for a WN command the time and date are ignored.
|
|
||||||
The duration is used to calculare the number of results to send.
|
|
||||||
|
|
||||||
The sip syntax for time is much flexibler.
|
|
||||||
The stub only support this format!
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import random
|
|
||||||
import socketserver
|
|
||||||
|
|
||||||
class sipProtocol(socketserver.BaseRequestHandler):
|
|
||||||
|
|
||||||
def match(self, m):
|
|
||||||
return(self.data.find(m.encode()) == 0)
|
|
||||||
|
|
||||||
def send(self, a):
|
|
||||||
a = "%s\r" % a
|
|
||||||
self.request.sendall(a.encode())
|
|
||||||
|
|
||||||
def read(self):
|
|
||||||
try:
|
|
||||||
self.data = self.request.recv(1024).strip()
|
|
||||||
except:
|
|
||||||
self.data = None
|
|
||||||
|
|
||||||
def meting(self):
|
|
||||||
res = ""
|
|
||||||
sep = "! "
|
|
||||||
if self.data[18:19] == b'0':
|
|
||||||
h = int(self.data[19:20].decode())
|
|
||||||
else:
|
|
||||||
h = int(self.data[18:20].decode())
|
|
||||||
if self.data[21:22] == b'0':
|
|
||||||
m = int(self.data[22:23].decode())
|
|
||||||
else:
|
|
||||||
m = int(self.data[21:23].decode())
|
|
||||||
aantal = 1+(60*h+m)//10
|
|
||||||
if self.data[-1:] == b'A':
|
|
||||||
data = "%i/10"
|
|
||||||
else:
|
|
||||||
data = "%i/10/0"
|
|
||||||
for i in range(aantal):
|
|
||||||
res += sep+data % i
|
|
||||||
sep=";"
|
|
||||||
self.send(res)
|
|
||||||
|
|
||||||
def handle(self):
|
|
||||||
self.read()
|
|
||||||
while self.data:
|
|
||||||
if self.match("LI USER,PASS"):
|
|
||||||
self.send("!")
|
|
||||||
elif self.match("TI LMW"):
|
|
||||||
self.send("! 20-JAN-01 00:00:00")
|
|
||||||
elif self.match("WN LMW,DUMMY,D10"):
|
|
||||||
self.meting()
|
|
||||||
elif self.match("LO"):
|
|
||||||
self.send("!")
|
|
||||||
else:
|
|
||||||
self.send("? ERROR")
|
|
||||||
self.read()
|
|
||||||
|
|
||||||
class sipServer(socketserver.TCPServer):
|
|
||||||
def __init__(self):
|
|
||||||
self.port = None
|
|
||||||
while self.port == None:
|
|
||||||
self.port = random.randint(20000, 50000)
|
|
||||||
try:
|
|
||||||
super(sipServer, self).__init__(("localhost", self.port), sipProtocol)
|
|
||||||
except:
|
|
||||||
self.port = None
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.pid = os.fork()
|
|
||||||
if self.pid == 0:
|
|
||||||
self.serve_forever()
|
|
||||||
|
|
||||||
def kill(self):
|
|
||||||
if self.pid != 0:
|
|
||||||
os.kill(self.pid, 15)
|
|
||||||
self.server_close()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
pass
|
|
Reference in New Issue
Block a user