1
|
|
|
""" |
2
|
|
|
Get flows (and other parameters) from h2oline.com sites |
3
|
|
|
""" |
4
|
|
|
import datetime |
5
|
|
|
import logging |
6
|
|
|
import re |
7
|
|
|
|
8
|
|
|
from bs4 import BeautifulSoup |
9
|
|
|
import requests |
10
|
|
|
import parsedatetime |
11
|
|
|
|
12
|
|
|
from app.models import Sensor |
13
|
|
|
from .base import add_new_sample, RemoteGage |
14
|
|
|
|
15
|
|
|
logger = logging.getLogger(__name__) |
16
|
|
|
|
17
|
|
|
|
18
|
|
|
class H2Oline(RemoteGage): |
19
|
|
|
@staticmethod |
20
|
|
|
def soup(remote_id): |
21
|
|
|
""" |
22
|
|
|
Return a beautiful soup object from h2oline |
23
|
|
|
""" |
24
|
|
|
url = 'http://www.h2oline.com/default.aspx?pg=si&op={}'.format(remote_id) |
25
|
|
|
r = requests.get(url) |
26
|
|
|
return BeautifulSoup(r.text, 'html.parser') |
27
|
|
|
|
28
|
|
|
def river(self, remote_id, soup=None): |
29
|
|
|
""" |
30
|
|
|
Return string with river name and location |
31
|
|
|
""" |
32
|
|
|
if soup is None: |
33
|
|
|
soup = self.soup(remote_id) |
34
|
|
|
river_strings = soup.body.findAll(text=re.compile(str(remote_id))) |
35
|
|
|
return ' '.join(river_strings[0].split()[1:]) |
36
|
|
|
|
37
|
|
|
def value_strings(self, remote_id, parameter='CFS', soup=None): |
38
|
|
|
""" |
39
|
|
|
Return strings containing specified parameter |
40
|
|
|
""" |
41
|
|
|
if soup is None: |
42
|
|
|
soup = self.soup(remote_id) |
43
|
|
|
p = re.compile('([\d.]+)+(?= {})'.format(parameter)) |
44
|
|
|
return soup.body.findAll(text=p) |
45
|
|
|
|
46
|
|
|
@staticmethod |
47
|
|
|
def start_end(string, parameter): |
48
|
|
|
""" |
49
|
|
|
Return the start and end of the parameter in the string |
50
|
|
|
""" |
51
|
|
|
p = re.compile('([\d.]+)+(?= {})'.format(parameter)) |
52
|
|
|
result = p.search(string) |
53
|
|
|
return result.start(), result.end() |
54
|
|
|
|
55
|
|
|
def value(self, remote_id, parameter='CFS', soup=None): |
56
|
|
|
""" |
57
|
|
|
Return float of first CFS found |
58
|
|
|
If given a parameter string, it will find that instead |
59
|
|
|
""" |
60
|
|
|
if soup is None: |
61
|
|
|
cfs_strings = self.value_strings(remote_id, parameter=parameter) |
62
|
|
|
else: |
63
|
|
|
cfs_strings = self.value_strings(remote_id, parameter=parameter, soup=soup) |
64
|
|
|
start, end = self.start_end(cfs_strings[0], parameter) |
65
|
|
|
return float(cfs_strings[0][start:end]) |
66
|
|
|
|
67
|
|
|
|
68
|
|
|
def dt_value(self, remote_id, parameter='CFS', soup=None): |
69
|
|
|
""" |
70
|
|
|
Returns datetime and float of first CFS (or other parameter) found |
71
|
|
|
""" |
72
|
|
|
strings = self.value_strings(remote_id, |
73
|
|
|
parameter=parameter, |
74
|
|
|
soup=soup) |
75
|
|
|
start, end = self.start_end(strings[0], parameter) |
76
|
|
|
dt = datetime.datetime.now() |
77
|
|
|
return dt, float(strings[0][start:end]) |
78
|
|
|
|
79
|
|
|
def get_sample(self, sensor_id): |
80
|
|
|
""" |
81
|
|
|
Takes a sensor id, tries to get the latest sample from the site |
82
|
|
|
""" |
83
|
|
|
sensor = self.sensor(sensor_id) |
84
|
|
|
if sensor.remote_parameter is None: |
85
|
|
|
dt, v = self.dt_value(sensor.remote_id) |
86
|
|
|
else: |
87
|
|
|
dt, v = self.dt_value(sensor.remote_id, |
88
|
|
|
parameter=sensor.remote_parameter) |
89
|
|
|
add_new_sample(sensor.id, dt, v) |
90
|
|
|
|