124 Commits

Author SHA1 Message Date
ef778c3e0a BUG FIX: cmdWrite fix
All checks were successful
build / build (push) Successful in 1m34s
2024-04-24 16:07:58 +02:00
49eb1522b6 Versie update: cmdWrite fix
Some checks failed
build / build (push) Has been cancelled
2024-04-24 16:06:15 +02:00
cdeeceeb55 Werkende upload
All checks were successful
build / build (push) Successful in 1m33s
2024-04-07 22:59:11 +02:00
64089ce72c Versie 0.9.7 2024-04-05 16:35:37 +02:00
7683ec29e9 Cleanup of module documentation
Some checks failed
build / build (push) Failing after 1m29s
2024-04-05 16:27:54 +02:00
285b3514a8 Added cmdWrite 2024-04-05 16:19:55 +02:00
f32c007b3f lmwParameter comment in class comment geplaats
All checks were successful
build / build (push) Successful in 1m45s
2024-04-04 21:52:34 +02:00
014dc507cc Commentaar toegevoegd voor lmwParamers 2024-04-04 21:39:47 +02:00
cec151e564 Overgang gitea action
All checks were successful
build / build (push) Successful in 1m44s
2024-02-18 22:08:14 +01:00
26f1caa60e Aanpassing pre-commit 2024-02-18 22:05:47 +01:00
7092e69e6a Nieuwe python versies toegevoegd in tox test 2024-01-21 20:42:51 +01:00
b32bce956f Extra parameters aan lijst toegevoegd
All checks were successful
continuous-integration/drone/push Build is passing
2022-11-02 10:47:47 +01:00
22bb4e6bd3 Updates .drone
Some checks failed
continuous-integration/drone/push Build is failing
2022-06-30 10:52:31 +02:00
49954d762b Updates .drone
Some checks failed
continuous-integration/drone/push Build is failing
2022-06-30 10:24:31 +02:00
30504239e1 Versie verhogen na cleartelnet fix
Some checks failed
continuous-integration/drone/push Build is failing
2022-06-29 18:20:27 +02:00
Marcel Nijenhof
42799296a9 Bug fix: Cleartelnet code werkte niet omdat deze in de if stond voor 0 bytes ontvangen.
Some checks failed
continuous-integration/drone/push Build is failing
2022-06-29 14:23:40 +00:00
Marcel Nijenhof
ac54b7cd0d Upload naar pypi org prod
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone Build is passing
2022-01-03 18:56:28 +01:00
Marcel Nijenhof
1df2a42196 Correctie .drone
Some checks reported errors
continuous-integration/drone/push Build is passing
continuous-integration/drone Build was killed
2022-01-03 18:42:44 +01:00
Marcel Nijenhof
2909ea7ed4 PYTHONPATH=src zodat lmwsip gevonden word
Some checks failed
continuous-integration/drone/push Build is failing
2022-01-03 18:39:16 +01:00
Marcel Nijenhof
f55d6c2e19 PYTHONPATH=. zodat llmwsip gevonden word
Some checks failed
continuous-integration/drone/push Build is failing
2022-01-03 18:38:08 +01:00
Marcel Nijenhof
664b215f16 Verplaatsen test directory
Some checks failed
continuous-integration/drone/push Build is failing
2022-01-03 18:32:08 +01:00
Marcel Nijenhof
5fe756ce97 Small corrections setup.cfg 2022-01-03 18:14:40 +01:00
Marcel Nijenhof
bf28862f1f Update README: install via pypi 2022-01-03 18:03:03 +01:00
Marcel Nijenhof
fe29441d1d Versie update
Some checks failed
continuous-integration/drone/push Build is failing
2022-01-02 23:50:13 +01:00
Marcel Nijenhof
d0043f3f18 Upload pypi test
Some checks failed
continuous-integration/drone/push Build is failing
2022-01-02 23:45:44 +01:00
Marcel Nijenhof
583997d64c Versie update
All checks were successful
continuous-integration/drone/push Build is passing
2021-12-31 23:18:45 +01:00
Marcel Nijenhof
04daf49b0a Update drone voor verplaatsing files
Some checks failed
continuous-integration/drone/push Build is failing
2021-12-31 23:16:26 +01:00
Marcel Nijenhof
b19f5d9049 Merge branch 'master' of https://git.marceln.org/Werk/lmwsip
Some checks failed
continuous-integration/drone/push Build is failing
2021-12-31 22:56:23 +01:00
Marcel Nijenhof
2052bfd2cc Verplaatse files. 2021-12-31 22:56:01 +01:00
Marcel Nijenhof
418d3e6041 Correctie pre-commit hoek 2021-12-31 22:54:49 +01:00
Marcel Nijenhof
08cd160713 Lokale test omgeschreven naar tox
Some checks failed
continuous-integration/drone/push Build is failing
2021-12-31 22:42:04 +01:00
Marcel Nijenhof
da80bd93d9 Files verwijderd uit oorspronkelijke dir. 2021-12-31 22:25:43 +01:00
Marcel Nijenhof
61997df1f3 Build weer werkend gemaakt.
Some checks failed
continuous-integration/drone/push Build is failing
2021-12-31 22:18:17 +01:00
Marcel Nijenhof
047bb783b7 Versie update
Some checks failed
continuous-integration/drone/push Build is failing
2021-12-29 15:14:53 +01:00
Marcel Nijenhof
281bbfdac4 Correctie setup.cfg voor upload pypi 2021-12-28 22:47:03 +01:00
Marcel Nijenhof
bcd761653f Aanpassing precommit hoek op setup.cfg 2021-12-28 22:27:42 +01:00
Marcel Nijenhof
f521992f58 pyproject.toml & setup.cfg toegevoegd 2021-12-28 22:22:39 +01:00
Marcel Nijenhof
230b929b4c Correctie druine build
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2021-12-08 17:46:24 +01:00
Marcel Nijenhof
a884a5295b BUG Bix:
Some checks failed
continuous-integration/drone/push Build is failing
LmwSip().lasttime("H10") --> LmwSip(host=None).lasttime("H10")

  Dit voorkomt het opzetten van een connectie.
  Dit veroorzaakte ook problemen in de zelftest.
2021-12-08 16:58:00 +01:00
Marcel Nijenhof
3414fde39c SYNTAX Correctie: log --> logging 2021-12-08 16:57:06 +01:00
Marcel Nijenhof
da6a9c3584 Correctie drone pipeline fedora 35
Some checks failed
continuous-integration/drone/push Build is failing
2021-12-01 23:06:45 +01:00
Marcel Nijenhof
73b15f58ca License toegevoegd
Some checks failed
continuous-integration/drone Build is failing
2021-12-01 22:01:05 +01:00
Marcel Nijenhof
f8f374569d Fix issue 12: lmwsip.run geeft stack trace.
All checks were successful
continuous-integration/drone/push Build is passing
- LmwSip object aangemaakt om tijd te bepalen.
 - Nog geen test code geschreven.
   Vergt uitzoeken hoe we door argparse heen kunnen testen.
2021-09-13 18:02:07 +02:00
Marcel Nijenhof
8d4a40389c valueStr added with quality
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-30 21:41:34 +02:00
Marcel Nijenhof
6a732a33c8 New version
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-30 16:29:36 +02:00
Marcel Nijenhof
f87e571e46 Merge branch 'master' of https://git.marceln.org/Werk/lmwsip
Some checks failed
continuous-integration/drone/push Build is failing
2021-08-30 16:26:01 +02:00
Marcel Nijenhof
4f593b008b Close issue 3 2021-08-30 16:21:54 +02:00
Marcel Nijenhof
34fe39371b use of lmwParameter for perion parameter.
Extra parameter xBS1x
2021-08-30 16:20:29 +02:00
Marcel Nijenhof
beadb51698 Fix issue 3 tijd voor 60 seconde parameters 2021-08-30 16:12:16 +02:00
Marcel Nijenhof
a7bc8a51c4 Test voor issue 3 2021-08-30 16:08:35 +02:00
Marcel Nijenhof
2f4f2eef3f Issue 3: Build H1 test 2021-08-30 16:05:25 +02:00
Marcel Nijenhof
d711b51ce5 use --extraindex-url for installation 2021-08-30 16:04:52 +02:00
Marcel Nijenhof
f2b7723210 Run install checck only on master 2021-08-30 16:04:05 +02:00
Marcel Nijenhof
7df03add42 Correctie email adres
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-08 14:25:39 +02:00
Marcel Nijenhof
9bd1d668da Correctie git hook
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-08 13:50:27 +02:00
Marcel Nijenhof
e9a65af74d Update README
Some checks failed
continuous-integration/drone/push Build is failing
2021-08-08 13:46:35 +02:00
Marcel Nijenhof
d7799db8fb Correctie .drone
Some checks failed
continuous-integration/drone/push Build is failing
2021-07-25 17:33:13 +02:00
Marcel Nijenhof
3b22676048 Correctie .drone version --> __version__
Some checks failed
continuous-integration/drone/push Build is failing
2021-07-25 17:25:07 +02:00
Marcel Nijenhof
0b8e763344 Correctie .drone depend --> depends
Some checks failed
continuous-integration/drone/push Build is failing
2021-07-25 17:22:51 +02:00
Marcel Nijenhof
707d4fc13a Correctie .drone.yml
Some checks failed
continuous-integration/drone/push Build is failing
2021-07-25 17:04:13 +02:00
Marcel Nijenhof
f29d49fafa Extra check yamllint .drone.yml 2021-07-25 17:03:51 +02:00
Marcel Nijenhof
3219139041 .drone yaml correctie
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2021-07-25 16:53:10 +02:00
Marcel Nijenhof
62c8b2021e Correctie .drone voor installCheck 2021-07-25 16:49:35 +02:00
Marcel Nijenhof
7091efe006 Correctie: UserWarning: Normalizing '0.1.05' to '0.1.5' 2021-07-25 16:47:13 +02:00
Marcel Nijenhof
2ae37db7a8 Nieuwe versie 2021-07-25 16:37:48 +02:00
Marcel Nijenhof
1556832ab2 Install check toegevoegd 2021-07-25 16:37:25 +02:00
Marcel Nijenhof
0b201743ba test.sip vervangen door io.StringIO file 2021-07-25 15:49:41 +02:00
Marcel Nijenhof
8e85c8ab3a Test voor docker python:3.6 en latest
Some checks failed
continuous-integration/drone/push Build is failing
2021-07-25 10:42:38 +02:00
Marcel Nijenhof
9feac5c8eb Copy fout drone.yml
All checks were successful
continuous-integration/drone/push Build is passing
2021-07-19 00:04:53 +02:00
Marcel Nijenhof
aa7ae08863 Test voor CentOS8 en Ubuntu 18.04 2021-07-19 00:01:05 +02:00
Marcel Nijenhof
3890abb479 Versie update: test CentOS7 & python 3.6
All checks were successful
continuous-integration/drone/push Build is passing
2021-07-18 15:17:21 +02:00
Marcel Nijenhof
2181afeb2a Correctie test op centos 7 2021-07-18 15:16:11 +02:00
Marcel Nijenhof
69dc25fcba Syntax correctie & keep yamlint happy
Some checks failed
continuous-integration/drone/push Build is failing
2021-07-18 14:38:56 +02:00
Marcel Nijenhof
b5e2dad196 Test nu op f34 en CentOS7 2021-07-18 14:26:53 +02:00
Marcel Nijenhof
fe564e5721 Bug fix: hang/loop in sendrecv
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-25 15:19:57 +01:00
Marcel Nijenhof
2b2aaa7336 Extra commentaar
All checks were successful
continuous-integration/drone/push Build is passing
2021-02-18 14:39:45 +01:00
Marcel Nijenhof
00d9d64f50 Versie nummer in de module 2021-02-16 16:16:42 +01:00
830aebdfa4 Fix voor: #8 Bug timeSerie("WN", "MWAD", xHm0")
Some checks failed
continuous-integration/drone/push Build is failing
- Tabel met lmw parameters opgenomen.
 - Period functie aangemaakt
 - Aanpassingen timeSerie en _roundtime_
 - Aanpassingen testen D10 --> H10 (D10 bestaat niet in lmw parameter tabel)
2020-12-04 11:25:23 +01:00
Marcel Nijenhof
08af855c45 Correctie issue 6 & 7
All checks were successful
continuous-integration/drone/push Build is passing
2020-11-08 14:23:38 +01:00
Marcel Nijenhof
23f9723d27 Test met cleartelnet 2020-11-08 14:00:21 +01:00
Marcel Nijenhof
3001b434a6 Aanpassingen reconnectcheck
- reconnectcheck naar sendrecv
 - idleconnect check
 - test voor idleconnect
2020-11-08 13:49:12 +01:00
Marcel Nijenhof
17301b70b3 reconnect test 2020-11-08 13:12:53 +01:00
Marcel Nijenhof
57f6619c80 Reconnect on socket failure 2020-11-08 12:32:37 +01:00
Marcel Nijenhof
5968b6ff5b Exception response in recv na close 2020-11-07 13:47:54 +01:00
Marcel Nijenhof
ad1fed8340 Extra close commando om timeouts te simuleren 2020-11-07 13:47:16 +01:00
Marcel Nijenhof
42133b80bd Logger in debug mode tijdens testen 2020-11-07 13:12:38 +01:00
Marcel Nijenhof
13fea782d7 Close socket na login failure 2020-11-07 12:27:28 +01:00
Marcel Nijenhof
bf1996931e BUG Fix: reconnect time > 0 toegevoegd
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-16 08:50:38 +02:00
eccd9011a3 Correctie een regel te veel verwijderd in reconnect
Some checks failed
continuous-integration/drone/push Build is failing
2020-10-15 19:25:07 +02:00
872f77037b Vereenvoudiging reconnect mechanisme
Some checks failed
continuous-integration/drone/push Build is failing
2020-10-15 19:21:39 +02:00
Marcel Nijenhof
4422dd4fe5 Versie verhoogt naar 0.0.7 naar verbeteringen
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-03 17:08:44 +02:00
Marcel Nijenhof
0d44e053cf Fix test voor extra argument git run 2020-10-03 17:08:09 +02:00
Marcel Nijenhof
5b296a1da7 Vlag voor accepteren certificaat 2020-10-03 17:03:01 +02:00
Marcel Nijenhof
81511300bf Extra test login fout 2020-10-03 15:27:19 +02:00
Marcel Nijenhof
6dd1d36add Fix argument raise LmwLoginFailure 2020-10-03 14:49:40 +02:00
Marcel Nijenhof
640c058d98 Versie verhoogd
All checks were successful
continuous-integration/drone/push Build is passing
2020-10-01 16:32:03 +02:00
Marcel Nijenhof
a8583d3eec Merge branch 'master' of https://git.marceln.org/Werk/lmwsip
Some checks failed
continuous-integration/drone/push Build is failing
2020-10-01 16:28:41 +02:00
Marcel Nijenhof
6c7a505775 Type: waring --> warning 2020-10-01 16:28:32 +02:00
Marcel Nijenhof
3d66a31792 Versie verhoogd
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-16 23:15:21 +02:00
Marcel Nijenhof
b79438209b Extra test voor value toegevoegd 2020-09-16 23:14:57 +02:00
Marcel Nijenhof
5b45b077f6 Afhankelijkheid dateutil toegevoegd aan setup 2020-09-16 23:14:31 +02:00
Marcel Nijenhof
5f4b5d7d7d drone: Correctie
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-08 17:25:20 +02:00
Marcel Nijenhof
6e3a21c6c4 test: Correctie import
Some checks failed
continuous-integration/drone/push Build is failing
2020-09-08 17:22:56 +02:00
Marcel Nijenhof
2281ef9427 Cleanup & correctie tests
Some checks failed
continuous-integration/drone/push Build is failing
2020-09-08 17:19:47 +02:00
Marcel Nijenhof
1bfa73a0f7 Update versie na correctie test folder
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-08 16:53:10 +02:00
Marcel Nijenhof
04667dc28c Correctie locatie tests directory
Some checks failed
continuous-integration/drone/push Build is failing
2020-09-08 16:52:28 +02:00
Marcel Nijenhof
dea73c249f Correctie lokatie test sip file na hernoemen
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-08 16:41:27 +02:00
Marcel Nijenhof
62456fd35b Type: test --> tests
Some checks failed
continuous-integration/drone/push Build is failing
2020-09-08 16:40:04 +02:00
Marcel Nijenhof
7ba9e27e14 Drone: ls -l van packagedir na file copy
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-08 15:13:53 +02:00
Marcel Nijenhof
dd47094b75 Correctie naam package in setup
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-08 15:12:39 +02:00
Marcel Nijenhof
da5da044ef Drone: correctie pipeline
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-08 15:08:46 +02:00
Marcel Nijenhof
8159dc83da Drone: correctie pipeline
Some checks failed
continuous-integration/drone/push Build is failing
2020-09-08 15:06:01 +02:00
Marcel Nijenhof
6900b9fc57 Drone: correctie pipeline 2020-09-08 15:05:33 +02:00
Marcel Nijenhof
7aa6ffc3d4 Drone: Correctie
Some checks failed
continuous-integration/drone/push Build is failing
2020-09-08 15:00:55 +02:00
Marcel Nijenhof
03503da5a4 Drone step toegevoegd voor klaar zetten in download
Some checks failed
continuous-integration/drone/push Build is failing
2020-09-08 14:59:39 +02:00
Marcel Nijenhof
80b8ebe4ff Test sip file toegevoegd
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-08 14:44:07 +02:00
Marcel Nijenhof
7e6751f60d Aanpassing drone pipeline test stap
Some checks failed
continuous-integration/drone/push Build is failing
2020-09-08 14:41:06 +02:00
Marcel Nijenhof
76407e2a86 Extra test voor lmwsip.run.run()
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-08 14:36:07 +02:00
Marcel Nijenhof
6885b03d40 Extra test voor lmwsip.run.run() 2020-09-08 14:35:40 +02:00
Marcel Nijenhof
3a07310e86 lmwsip.run close van socket 2020-09-08 14:35:14 +02:00
Marcel Nijenhof
8acaf98e4b logging warn --> warning 2020-09-08 14:34:36 +02:00
Marcel Nijenhof
a2b8a52d47 Logging toegevoegd 2020-09-08 13:39:32 +02:00
Marcel Nijenhof
df36ae495c Aanpassing siprun naar lmwsip.run module
All checks were successful
continuous-integration/drone/push Build is passing
- Splitsing losse run functie
 - Aanpassing documentatie
2020-09-08 13:11:15 +02:00
Marcel Nijenhof
827807be73 Build package toegevoegd aan pipeline
All checks were successful
continuous-integration/drone/push Build is passing
2020-09-04 22:56:19 +02:00
16 changed files with 1468 additions and 666 deletions

View File

@@ -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

View File

@@ -0,0 +1,21 @@
---
name: build
on:
- push
jobs:
build:
runs-on: fedora-builder
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Build package
run: python3 -m build
- name: run tox
run: tox
- name: Upload na pypi
env:
TWINE_USERNAME: ${{ secrets.PYPI_USER }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
if: github.ref_type == 'tag'
run: python3 -m twine upload dist/*

4
.gitignore vendored
View File

@@ -1,8 +1,10 @@
*.pyc
*.sip
tmp
__pycache__
build
dist
lmwsip_marceln.egg-info
test/__pycache__
lmwsip.egg-info
*.swp
.tox

21
LICENSE
View File

@@ -1 +1,20 @@
TODO
Copyright (c) 2021 Rijkswaterstaat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -3,38 +3,30 @@
lmwsip is a python library for the lmw sip protocol.
## Library
## Package
The lmwsip.py library contains the class LmwSip to connect to the
LMW meetnet using de SIP protocol. The library contains documentation
The lmwsip package contains the class LmwSip to connect to the
[LMW](https://waterberichtgeving.rws.nl/water-en-weer/metingen/lmw-info)
meetnet using de SIP protocol. The library contains documentation
how to use it.
## Tools
### lmwsip-test
## Installing
A small test program containing some functions to test the library.
Just install the package with 'pip':
### siprun
A prgram to run SIP command files.
See "siprun -H" for usage information.
#### hoek-h10.sip
A sample sip command file to request the waterlevel at hoek van holland
from the last hour
## Username password
All files contain "USER", "PASS".
These values should be replaced by real credentials.
Otherwise the connection fails.
```
pip install lmwsip
```
## Examples
### Library
### Username password
#### Use send (low level)
All examples contain "USER", "PASS".
These values should be replaced by real credentials.
Otherwise the connection fails.
### Use send (low level)
``` python
from lmwsip import LmwSip
@@ -71,16 +63,29 @@ sip = LmwSip("USER", "PASS")
pprint(sip.timeSerie("WN", "HOEK", "H10", start, end).ts)
```
### siprun
### lmwsip.run
```
$ ./siprun -h sip-lmw.ad.rws.nl -s -p 443 hoek-h10.sip
$ python -m lmwsip.run /tmp/hoek-h10.sip
> [LI USER,PASS]
< [! ]
> [TI LMW]
< [! 05-SEP-19 08:24:43]
> [WN LMW,HOEK,H10,-25:00,05-09-2019,08:10,DATA]
< [? 0211 Waarnemingen vallen buiten opslag range]
< [! 08-SEP-20 12:03:27]
> [WN LMW,HOEK,H10,-01:00,08-09-2020,11:50,DATA]
< [! -17/50;-21/50;-24/50;-26/50;-27/50;-28/50;-28/50]
> [LO]
< [! ]
```
## Unit tests
The code containts a python unittest.
This code runs a dummy sip server and runs a number of test against the dummy
server.
## Git pre commit hook
There is a pre-commit `githooks/pre-commit' with two functions:
* Updating the `__version__` in the module from setup.py
* Running the unit test code.
* Running a syntaxt test.

11
githooks/pre-commit Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/sh
set -e
yamllint .gitea/workflows/*yml
VERSION=$(grep version setup.cfg | sed 's/.*= *//')
sed -i "s/^__version__ = .*/__version__ = '${VERSION}'/" src/lmwsip/__init__.py
git add src/lmwsip/__init__.py
tox

View File

@@ -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))

6
pyproject.toml Normal file
View File

@@ -0,0 +1,6 @@
[build-system]
requires = [
"setuptools>=42",
"wheel"
]
build-backend = "setuptools.build_meta"

25
setup.cfg Normal file
View File

@@ -0,0 +1,25 @@
[metadata]
name = lmwsip
version = 0.9.8
author = Marcel Nijenhof
author_email = pypi@marceln.org
description = Interface for the lmw sip protocol
long_description = file: README.md
long_description_content_type = text/markdown
url = https://git.marceln.org/Werk/lmwsip
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: OS Independent
Development Status :: 4 - Beta
[options]
package_dir =
= src
install_requires =
python-dateutil
packages = find:
python_requires = >= 3.6
[options.packages.find]
where = src

View File

@@ -1,22 +1,4 @@
import setuptools
from setuptools import setup
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',
)
if __name__ == "__main__":
setup()

1103
src/lmwsip/__init__.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,33 +3,16 @@
import sys
import getopt
import argparse
import logging
from lmwsip import LmwSip
def main():
lastTime=LmwSip.lasttime(None, "H10")
parser = argparse.ArgumentParser(description="Run a sip file.")
parser.add_argument("-u", "--unencrypted", action="store_true",
help="Run a sip connection without ssl")
parser.add_argument("-c", "--cleartelnet", action="store_true",
help="Clear telnet protocol in tcp session")
parser.add_argument("-H", "--host", action='store',
default="sip-lmw.rws.nl",
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 run(args):
logging.basicConfig(level=args.debug)
logging.debug("lmwsip.run %s" % args)
try:
lmwsip = LmwSip(host=args.host, port=args.port,
ssl=not args.unencrypted,
check_ssl=not args.acceptssl,
cleartelnet=args.cleartelnet)
except Exception as e:
print("Connect to lmw failed: %s" % e)
@@ -45,6 +28,37 @@ def main():
print("< [%s]" % (lmwsip.recv().strip('\r')))
except:
pass
try:
lmwsip.closesocket()
except:
pass
def main():
lastTime=LmwSip(host=None).lasttime("H10")
parser = argparse.ArgumentParser(description="Run a sip file.")
parser.add_argument("-u", "--unencrypted", action="store_true",
help="Run a sip connection without ssl")
parser.add_argument("-a", "--acceptssl", action="store_true",
help="Accept ssl certificate")
parser.add_argument("-c", "--cleartelnet", action="store_true",
help="Clear telnet protocol in tcp session")
parser.add_argument("-H", "--host", action='store',
default="sip-lmw.rws.nl",
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("-D", "--debug", action='store',
default="WARN",
help="Debug level")
parser.add_argument("files", type=argparse.FileType('r'), nargs="+",
help="Sip files to run")
run(parser.parse_args())
if __name__ == "__main__":
main()

View File

@@ -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()

168
tests/main.py Executable file
View File

@@ -0,0 +1,168 @@
#!/usr/bin/python
import sys
import io
import unittest
import lmwsip
import stubSipServer
import logging
from stubSipServer import sipServer
from lmwsip.run import run
from datetime import datetime, timedelta
from dateutil import tz
from time import sleep
class myTestArgs():
pass
class lmwsipTest(unittest.TestCase):
def setUp(self):
self.sipserver = sipServer()
self.sip = None
self.sipserver.run()
def login(self, **args):
log = logging.basicConfig(level=logging.DEBUG)
self.sip = lmwsip.LmwSip("USER", "PASS", "localhost",
self.sipserver.port, ssl=False,
log=log, **args)
def tearDown(self):
if self.sip:
self.sip.closesocket()
self.sipserver.kill()
def test_sipobj(self):
self.login()
self.assertEqual(type(self.sip), lmwsip.LmwSip)
def test_H1(self):
self.sip = lmwsip.LmwSip(host=None)
self.assertEqual(self.sip.period('H1'), 1)
def test_H10(self):
self.sip = lmwsip.LmwSip(host=None)
self.assertEqual(self.sip.period('H10'), 10)
def test_xHm0(self):
self.sip = lmwsip.LmwSip(host=None)
self.assertEqual(self.sip.period('xHm0'), 10)
def test_Noparm(self):
self.sip = lmwsip.LmwSip(host=None)
with self.assertRaises(lmwsip.LmwParmWarn):
self.assertEqual(self.sip.period('Noparm'), None)
def test_loginfail(self):
with self.assertRaises(lmwsip.LmwLoginFailure):
self.sip = lmwsip.LmwSip("FAIL", "FAIL", "localhost",
self.sipserver.port, ssl=False)
def test_ti(self):
self.login()
self.assertEqual(type(self.sip.ti()), str)
def test_telnetti(self):
self.login(cleartelnet=True)
self.assertEqual(type(self.sip.ti()), str)
def test_cmd(self):
self.login()
self.assertEqual(type(self.sip.cmd("WN", "DUMMY", "H10", "+00:59", "2020-01-01", "00:00")), str)
def test_cmderr(self):
self.login()
with self.assertRaises(lmwsip.LmwCmdWarn):
self.assertEqual(type(self.sip.cmd("NOP", "DUMMY", "H10", "+00:59", "2020-01-01", "00:00")), str)
def test_cmdWrite(self):
self.login()
self.assertEqual(type(self.sip.cmdWrite("WN", "DUMMY", "H10", "+00:20", "2020-01-01", "00:00", "35/10;33/10")), str)
def test_value(self):
self.login()
self.assertEqual(type(self.sip.value("WN", "DUMMY", "H10")), str)
def test_value1min(self):
self.login()
self.assertEqual(type(self.sip.value("WN", "DUMMY", "H1")), str)
def test_valueStr(self):
self.login()
self.assertEqual(type(self.sip.valueStr("WN", "DUMMY", "H10")), str)
def test_logout(self):
self.login()
self.assertEqual(self.sip.logout(), None)
def test_lmwTimeSerie(self):
self.login()
timezone = tz.gettz('GMT+1')
res = self.sip.timeSerie("WN", "DUMMY", "H10",
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):
self.login()
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, timedelta(minutes=10)), t1)
self.assertEqual(self.sip._roundtime_(t2, timedelta(minutes=10)), t1)
def test_closerecv(self):
self.login()
self.sip.send("CLOSE")
with self.assertRaises(lmwsip.LmwSipConnectError):
self.sip.recv()
def test_closeti(self):
self.login()
self.sip.send("CLOSE")
self.assertEqual(type(self.sip.ti()), str)
def test_closecmd(self):
self.login()
self.sip.send("CLOSE")
self.assertEqual(type(self.sip.cmd("WN", "DUMMY", "H10", "+00:59", "2020-01-01", "00:00")), str)
def test_reconnect(self):
self.login(reconnecttime=1)
sleep(2)
self.assertEqual(self.sip.sendrecv("LOGOUTCOUNT"), "1\r")
def test_idlereconnect(self):
self.login(idlereconnect=1)
sleep(2)
self.assertEqual(self.sip.sendrecv("LOGOUTCOUNT"), "1\r")
def test_versionstr(self):
self.assertEqual(type(lmwsip.__version__), str)
def test_run(self):
capturedOutput = io.StringIO()
sys.stdout = capturedOutput
testSipFile = io.StringIO("LI USER,PASS\rTI LMW\rLO")
testSipFile.seek(0)
args = myTestArgs()
args.debug = "DEBUG"
args.host = "localhost"
args.port = self.sipserver.port
args.unencrypted = True
args.acceptssl = True
args.cleartelnet = False
args.time = "+00:59"
args.date = "2020-01-01"
args.files = [testSipFile]
run(args)
args.files[0].close()
self.assertEqual(capturedOutput.getvalue().find("!")>= 0, True)
self.assertEqual(capturedOutput.getvalue().find("?"), -1)
if __name__ == '__main__':
unittest.main()

View File

@@ -13,12 +13,15 @@ Implements the following commands:
CMD> TI LMW
ANS< ! 20-JAN-01 00:00:00
CMD> WN LMW,DUMMY,D10,+HH:MM,yyyy-mm-dd,HH:MM,DATA
CMD> WN LMW,DUMMY,H10,+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
CMD> WN LMW,DUMMY,H10,+HH:MM,yyyy-mm-dd,HH:MM,DATB
ANS< ! 1/10/0;2/10/0;....
CMD> WN LMW,DUMMY,H1,+HH:MM,yyyy-mm-dd,HH:MM,DATA
ANS< ! 1/10,;2/10;....
CMD> LO
ANS< !
@@ -41,8 +44,9 @@ import time
import random
import socketserver
class sipProtocol(socketserver.BaseRequestHandler):
logoutcount=0
class sipProtocol(socketserver.BaseRequestHandler):
def match(self, m):
return(self.data.find(m.encode()) == 0)
@@ -56,18 +60,19 @@ class sipProtocol(socketserver.BaseRequestHandler):
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
def number(self, b):
if b[0] == b'0':
return(int(b[0:1]))
else:
return(int(b[0:2]))
def meting(self, delta=10):
res = ""
sep = "! "
elem = self.data.decode().split(",")
h = self.number(elem[3][1:3])
m = self.number(elem[3][4:6])
aantal = 1+(60*h+m)//delta
if self.data[-1:] == b'A':
data = "%i/10"
else:
@@ -78,16 +83,24 @@ class sipProtocol(socketserver.BaseRequestHandler):
self.send(res)
def handle(self):
global logoutcount
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("WN LMW,DUMMY,H10,"):
self.meting(10)
elif self.match("WN LMW,DUMMY,H1,"):
self.meting(1)
elif self.match("LOGOUTCOUNT"):
self.send(str(logoutcount))
elif self.match("LO"):
logoutcount+=1
self.send("!")
elif self.match("CLOSE"):
self.request.close()
else:
self.send("? ERROR")
self.read()
@@ -113,4 +126,6 @@ class sipServer(socketserver.TCPServer):
self.server_close()
if __name__ == '__main__':
s = sipServer()
s.run()
pass

6
tox.ini Normal file
View File

@@ -0,0 +1,6 @@
[tox]
envlist = py36,py37,py38,py310,py311,py312,py313
[testenv]
deps = python-dateutil
commands = python tests/main.py