Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
H
HEV - High Energy Ventilator
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
5
Issues
5
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
HEV - High Energy Ventilator
Commits
4d5c269a
Commit
4d5c269a
authored
May 11, 2021
by
Dónal Murray
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify hevclient internals
parent
42df77bf
Pipeline
#1502
failed with stages
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
46 additions
and
61 deletions
+46
-61
hevclient.py
raspberry-dataserver/hevclient.py
+46
-61
No files found.
raspberry-dataserver/hevclient.py
View file @
4d5c269a
...
...
@@ -31,7 +31,7 @@ import time
import
json
import
threading
from
typing
import
List
,
Dict
,
Union
from
CommsCommon
import
P
ayloadFormat
,
P
AYLOAD_TYPE
from
CommsCommon
import
PAYLOAD_TYPE
import
logging
logging
.
basicConfig
(
...
...
@@ -45,80 +45,71 @@ class HEVPacketError(Exception):
class
HEVClient
(
object
):
def
__init__
(
self
,
polling
=
True
):
super
(
HEVClient
,
self
)
.
__init__
()
self
.
_alarms
=
[]
# db for alarms
self
.
_personal
=
None
# db for personal data
self
.
_fastdata
=
None
# db for sensor values
self
.
_readback
=
None
# db for sensor values
self
.
_cycle
=
None
# db for sensor values
self
.
_target
=
None
# db for sensor values
self
.
_logmsg
=
None
# db for sensor values
self
.
_thresholds
=
None
# db for sensor values
self
.
_thresholds
=
[]
# db for threshold settings
self
.
_polling
=
polling
# keep reading data into db
self
.
_lock
=
threading
.
Lock
()
# lock for the database
super
()
.
__init__
()
# alarms latch
self
.
_alarms
=
[]
# Last packet of each type
self
.
_last_packet
=
{
"PERSONAL"
:
None
,
"DATA"
:
None
,
"READBACK"
:
None
,
"CYCLE"
:
None
,
"TARGET"
:
None
,
"LOGMSG"
:
None
,
"THRESHOLDS"
:
None
,
}
# lock for the last packet storage
self
.
_lock
=
threading
.
Lock
()
# start polling in another thread unless told otherwise
self
.
_polling
=
polling
if
self
.
_polling
:
self
.
start_polling
()
def
start_polling
(
self
):
"""start worker thread to
update db
in the background"""
"""start worker thread to
get data
in the background"""
worker
=
threading
.
Thread
(
target
=
self
.
start_client
,
daemon
=
True
)
worker
.
start
()
def
start_client
(
self
)
->
None
:
"""synchronous wrapper for polling()"""
asyncio
.
run
(
self
.
polling
())
async
def
polling
(
self
)
->
None
:
"""open persistent connection with server"""
writer
=
None
data
=
None
while
True
:
try
:
reader
,
writer
=
await
asyncio
.
open_connection
(
"127.0.0.1"
,
54320
)
# grab data from the socket as soon as it is available and dump it in the db
while
self
.
_polling
:
try
:
# grab data from the socket as soon as it is available
data
=
await
reader
.
readuntil
(
separator
=
b
"
\0
"
)
data
=
data
[:
-
1
]
# snip off nullbyte
# snip off nullbyte and parse json
data
=
data
[:
-
1
]
payload
=
json
.
loads
(
data
.
decode
(
"utf-8"
))
if
payload
[
"type"
]
==
"keepalive"
:
# Still alive
payload_type
=
payload
[
"type"
]
# check that it's valid
if
payload_type
==
"keepalive"
:
# drop silently - without it the hevserver can go down unnoticed
continue
elif
payload
[
"type"
]
==
"DATA"
:
with
self
.
_lock
:
self
.
_fastdata
=
payload
[
"DATA"
]
elif
payload
[
"type"
]
==
"READBACK"
:
with
self
.
_lock
:
self
.
_readback
=
payload
[
"READBACK"
]
elif
payload
[
"type"
]
==
"CYCLE"
:
with
self
.
_lock
:
self
.
_cycle
=
payload
[
"CYCLE"
]
elif
payload
[
"type"
]
==
"TARGET"
:
with
self
.
_lock
:
self
.
_target
=
payload
[
"TARGET"
]
elif
payload
[
"type"
]
==
"PERSONAL"
:
elif
payload_type
in
self
.
_last_packet
:
# store it in the right place and pass it on
with
self
.
_lock
:
self
.
_personal
=
payload
[
"PERSONAL"
]
elif
payload
[
"type"
]
==
"LOGMSG"
:
with
self
.
_lock
:
self
.
_logmsg
=
payload
[
"LOGMSG"
]
elif
payload
[
"type"
]
==
"THRESHOLDS"
:
with
self
.
_lock
:
self
.
_thresholds
=
payload
[
"THRESHOLDS"
]
elif
payload
[
"type"
]
==
"ALARM"
:
with
self
.
_lock
:
self
.
_alarms
=
payload
[
"ALARM"
]
elif
payload
[
"type"
]
in
[
pt
.
name
for
pt
in
PAYLOAD_TYPE
]:
# payload type is a valid payload type
self
.
_last_packet
[
payload_type
]
=
payload
[
payload_type
]
elif
payload_type
in
[
pt
.
name
for
pt
in
PAYLOAD_TYPE
]:
# valid payload type but unimplemented in hevclient
# passing lets us still use alarm information vs continue
pass
else
:
# invalid packet - something seriously wrong with the hevserver
raise
HEVPacketError
(
"Invalid broadcast type"
)
self
.
_alarms
=
payload
[
"alarms"
]
# self._personal = payload["personal"]
self
.
get_updates
(
payload
)
# callback function to be overridden
except
json
.
decoder
.
JSONDecodeError
:
logging
.
warning
(
f
"Could not decode packet: {data}"
)
...
...
@@ -140,6 +131,7 @@ class HEVClient(object):
def
get_updates
(
self
,
payload
)
->
None
:
"""Overrideable function called after receiving data from the socket, with that data as an argument"""
logging
.
debug
(
payload
)
pass
async
def
_send_request
(
...
...
@@ -213,39 +205,32 @@ class HEVClient(object):
# def send_personal(self, personal: Dict[str, str]=None ) -> bool:
def
send_personal
(
self
,
personal
:
str
)
->
bool
:
#
acknowledge alarm to remove it from the hevserver list
#
send personal information
return
asyncio
.
run
(
self
.
_send_request
(
"PERSONAL"
,
personal
=
personal
))
# Getters to check last value of each datatype - debugging only
def
get_values
(
self
)
->
Dict
:
# get sensor values from db
return
self
.
_fastdata
return
self
.
_last_packet
[
"DATA"
]
def
get_readback
(
self
)
->
Dict
:
# get readback from db
return
self
.
_readback
return
self
.
_last_packet
[
"READBACK"
]
def
get_cycle
(
self
)
->
Dict
:
# get cycle data from db
return
self
.
_cycle
return
self
.
_last_packet
[
"CYCLE"
]
def
get_personal
(
self
)
->
Dict
:
# get personal data from db
return
self
.
_personal
return
self
.
_last_packet
[
"PERSONAL"
]
def
get_logmsg
(
self
)
->
Dict
:
# get logmsg data from db
return
self
.
_logmsg
return
self
.
_last_packet
[
"LOGMSG"
]
def
get_target
(
self
)
->
Dict
:
# get target data from db
return
self
.
_target
return
self
.
_last_packet
[
"TARGET"
]
def
get_thresholds
(
self
)
->
Dict
:
# get threshold data from db
return
self
.
_thresholds
return
self
.
_last_packet
[
"THRESHOLDS"
]
def
get_alarms
(
self
)
->
List
[
str
]:
# get alarms from db
return
self
.
_alarms
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment