Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
C
compact-slowcontrol
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
4
Issues
4
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
0
Merge Requests
0
Requirements
Requirements
List
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Test Cases
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issue
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Peter-Bernd Otte
compact-slowcontrol
Commits
0017c9d6
Commit
0017c9d6
authored
Aug 02, 2019
by
Peter-Bernd Otte
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added functionality to relais-control
parent
0e2633b2
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
95 additions
and
48 deletions
+95
-48
python/relais-control/config.yml
python/relais-control/config.yml
+21
-3
python/relais-control/relais-control.py
python/relais-control/relais-control.py
+54
-26
python/relais-control/relais.py
python/relais-control/relais.py
+20
-19
No files found.
python/relais-control/config.yml
View file @
0017c9d6
relais
:
-
hi
-
ti
# all parameters, except for MQTTRelaisTopic are optional
# - if debug is supplied, it will override the global -v option
# - defaultTopics, switchOffTopics, toggleTopics and inverseSwitchOnTopics are either
# lists or a sinlge string
testraum/testrelais
:
MQTTRelaisTopic
:
homie/fsr-ww/2
debug
:
true
defaultSwitchOffTime
:
5
defaultTopics
:
-
homie/enocean/test/schalter
-
homie/enocean/test/schalter2
switchOffTopics
:
-
homie/enocean/test/schalter3
toggleTopics
:
homie/enocean/test/schalter2
testraum/testrelais2
:
MQTTRelaisTopic
:
homie/fsr-ww/3
defaultSwitchOffTime
:
15
toggleTopics
:
homie/enocean/test/schalter2
\ No newline at end of file
python/relais-control/relais-control.py
View file @
0017c9d6
...
...
@@ -4,15 +4,12 @@ import json
import
time
from
datetime
import
datetime
import
paho.mqtt.client
as
paho
#import numbers
#import parse
from
relais
import
*
import
yaml
#pip3 install pyyaml
import
os
#for os.path.isfile
import
logging
,
argparse
format
=
"%(asctime)-9s %(levelname)-8s %(message)s"
logging
.
basicConfig
(
format
=
format
,
datefmt
=
"%H:%M:%S"
)
logging
.
basicConfig
(
format
=
"%(asctime)-15s %(levelname)-8s %(message)s"
)
logger
=
logging
.
getLogger
(
"Actor"
)
parser
=
argparse
.
ArgumentParser
(
description
=
'Workload distributor for trivial parallelism.'
)
...
...
@@ -23,12 +20,6 @@ parser.add_argument("mqtt_client_name", help="MQTT client name. Needs to be uniq
args
=
parser
.
parse_args
()
logger
.
setLevel
(
logging
.
WARNING
-
(
args
.
verbosity
*
10
if
args
.
verbosity
<=
2
else
20
)
)
#broker="dom"
#MQTTClientName = "I2CActor"
if
os
.
path
.
exists
(
args
.
config_file
):
logger
.
debug
(
"config file exists"
)
mlast
=
{}
def
on_connect
(
client
,
userdata
,
flags
,
rc
):
...
...
@@ -38,10 +29,14 @@ def on_connect(client, userdata, flags, rc):
# client.subscribe("#")
client
.
subscribe
(
x
.
MQTTRelaisTopic
)
for
y
in
x
.
defaultTopics
:
client
.
subscribe
(
y
)
logger
.
debug
(
"MQTT: "
+
x
.
MQTTname
+
" defaultTopics subscribed"
)
for
y
in
x
.
toggleTopics
:
client
.
subscribe
(
y
)
logger
.
debug
(
"MQTT: "
+
x
.
MQTTname
+
" toggleTopics subscribed"
)
for
y
in
x
.
switchOffTopics
:
client
.
subscribe
(
y
)
logger
.
debug
(
"MQTT: "
+
x
.
MQTTname
+
" switchOffTopics subscribed"
)
for
y
in
x
.
inverseSwitchOnTopics
:
client
.
subscribe
(
y
)
client
.
subscribe
(
x
.
MQTTName
+
"/set"
)
logger
.
debug
(
"MQTT: "
+
x
.
MQTTname
+
" inverseSwitchOnTopics subscribed"
)
client
.
subscribe
(
x
.
MQTTname
+
"/set"
)
logger
.
debug
(
"MQTT: Subscribed to all topics"
)
else
:
logger
.
error
(
"Bad connection. Return code="
+
str
(
rc
))
...
...
@@ -71,7 +66,7 @@ def on_message(client, userdata, message):
if
message
.
topic
==
x
.
MQTTRelaisTopic
:
x
.
relaisMsg
(
j
)
x
.
checkAction
(
message
.
topic
,
j
)
if
message
.
topic
==
x
.
MQTT
RelaisTopic
+
"/set"
:
if
message
.
topic
==
x
.
MQTT
name
+
"/set"
:
x
.
setV
(
j
[
'v'
],
j
[
'time'
])
mlast
[
message
.
topic
]
=
j
...
...
@@ -79,6 +74,51 @@ def on_message(client, userdata, message):
client
=
paho
.
Client
(
args
.
mqtt_client_name
)
# test with:
# mosquitto_pub -t homie/fsr-ww/1 -m '{"setv": 0, "time": 1564251546.330417, "type": "FUD14", "v": 1}'
# mosquitto_sub -t 'homie/I2CActor/testraum/testrelais' -v
relaisList
=
[]
debug
=
True
if
args
.
verbosity
>
1
else
False
if
os
.
path
.
exists
(
args
.
config_file
):
logger
.
debug
(
"config file exists"
)
with
open
(
"config.yml"
,
'r'
)
as
ymlfile
:
cfg
=
yaml
.
full_load
(
ymlfile
)
# see https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation
for
section
in
cfg
:
MQTTName
=
"homie/"
+
args
.
mqtt_client_name
+
"/"
+
section
logger
.
info
(
"Adding Relais with MQTT topic: "
+
MQTTName
)
logger
.
info
(
"Configuration: "
+
str
(
cfg
[
section
]))
if
"MQTTRelaisTopic"
not
in
cfg
[
section
]:
logger
.
error
(
"MQTTRelaisTopic property is missing. Will not be added."
)
continue
for
x
in
relaisList
:
if
x
.
MQTTRelaisTopic
==
cfg
[
section
][
"MQTTRelaisTopic"
]:
logger
.
error
(
"MQTTRelaisTopic: "
+
str
(
cfg
[
section
][
"MQTTRelaisTopic"
])
+
" does already exist. Will not be added."
)
continue
defaultTopics
=
cfg
[
section
][
"defaultTopics"
]
if
"defaultTopics"
in
cfg
[
section
]
else
[]
toggleTopics
=
cfg
[
section
][
"toggleTopics"
]
if
"toggleTopics"
in
cfg
[
section
]
else
[]
switchOffTopics
=
cfg
[
section
][
"switchOffTopics"
]
if
"switchOffTopics"
in
cfg
[
section
]
else
[]
inverseSwitchOnTopics
=
cfg
[
section
][
"inverseSwitchOnTopics"
]
if
"inverseSwitchOnTopics"
in
cfg
[
section
]
else
[]
# print(type(toggleTopics))
if
type
(
defaultTopics
)
is
not
list
:
defaultTopics
=
[
defaultTopics
]
if
type
(
toggleTopics
)
is
not
list
:
toggleTopics
=
[
toggleTopics
]
if
type
(
switchOffTopics
)
is
not
list
:
toggleTopics
=
[
switchOffTopics
]
if
type
(
inverseSwitchOnTopics
)
is
not
list
:
toggleTopics
=
[
inverseSwitchOnTopics
]
defaultSwitchOffTime
=
cfg
[
section
][
"defaultSwitchOffTime"
]
if
"defaultSwitchOffTime"
in
cfg
[
section
]
else
None
debugItem
=
cfg
[
section
][
"debug"
]
if
"debug"
in
cfg
[
section
]
else
debug
relaisList
.
append
(
relais
(
MQTTClient
=
client
,
MQTTName
=
MQTTName
,
MQTTRelaisTopic
=
cfg
[
section
][
"MQTTRelaisTopic"
],
toggleTopics
=
toggleTopics
,
switchOffTopics
=
switchOffTopics
,
defaultTopics
=
defaultTopics
,
inverseSwitchOnTopics
=
inverseSwitchOnTopics
,
defaultSwitchOffTime
=
defaultSwitchOffTime
,
debug
=
debugItem
))
logger
.
info
(
"Adding successfully."
)
client
.
on_message
=
on_message
client
.
on_connect
=
on_connect
client
.
on_disconnect
=
on_disconnect
...
...
@@ -87,25 +127,13 @@ client.connect(args.mqtt_broker_host)
client
.
loop_start
()
#start loop to process received messages in separate thread
logger
.
debug
(
"MQTT Loop started."
)
# test with:
# mosquitto_pub -t homie/fsr-ww/1 -m '{"setv": 0, "time": 1564251546.330417, "type": "FUD14", "v": 1}'
# mosquitto_sub -t 'homie/I2CActor/testraum/testrelais' -v
relaisList
=
[]
relaisList
.
append
(
relais
(
MQTTClient
=
client
,
MQTTName
=
"homie/"
+
args
.
mqtt_client_name
+
"/testraum/testrelais"
,
MQTTRelaisTopic
=
"homie/fsr-ww/2"
,
toggleTopics
=
[
"homie/enocean/test/schalter2"
],
switchOffTopics
=
[
"homie/enocean/test/schalter3"
],
defaultTopics
=
[
"homie/enocean/test/schalter"
,
'homie/enocean/wohnzimmer/bewegungsmelder/bewegungsmelderDeckeGaube'
,
'homie/enocean/bügelzimmerUG/bewegungsmelder/bewegungsmelderDecke'
],
defaultSwitchOffTime
=
5
))
#relaisList.append(relais("testraum/testrelais2", "homie/fsr-ww/2", ["test/schalter2"], 5))
sleepTime
=
1
if
args
.
verbosity
>
0
else
0.025
while
True
:
for
x
in
relaisList
:
x
.
check
()
# x.relaisMsg(json.loads('{"time": 1564578103.410478, "type": "FSR14", "setv": 1.0, "v": 1.0}'))
time
.
sleep
((
1
-
time
.
time
()
%
1
)
/
1
)
#every second, even if the processing before took longer
time
.
sleep
((
1
-
time
.
time
()
%
1
)
*
sleepTime
)
#every second, even if the processing before took longer
client
.
disconnect
()
client
.
loop_stop
()
\ No newline at end of file
python/relais-control/relais.py
View file @
0017c9d6
...
...
@@ -21,9 +21,10 @@ class rLightDesire(Enum):
class
relais
:
def
__init__
(
self
,
MQTTClient
,
MQTTName
,
MQTTRelaisTopic
,
defaultTopics
=
None
,
toggleTopics
=
None
,
switchOffTopics
=
None
,
inverseSwitchOnTopics
=
None
,
defaultSwitchOffTime
=
None
):
inverseSwitchOnTopics
=
None
,
defaultSwitchOffTime
=
None
,
debug
=
False
):
self
.
MQTTname
=
MQTTName
#string
self
.
type
=
"relais"
self
.
debug
=
debug
self
.
MQTTClient
=
MQTTClient
#object
self
.
MQTTRelaisTopic
=
MQTTRelaisTopic
#string
...
...
@@ -51,7 +52,7 @@ class relais:
"v"
:
self
.
v
,
"time"
:
t
,
"reason"
:
reason
},
sort_keys
=
True
),
qos
=
1
,
retain
=
True
)
def
relaisMsg
(
self
,
j
):
print
(
"Feedback-Msg from Relais ("
,
self
.
MQTTname
,
")
: "
,
j
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"Feedback-Msg from Relais
: "
,
j
)
if
self
.
v
is
None
:
self
.
v
=
j
[
'v'
]
if
self
.
timeLastChange
is
None
:
self
.
timeLastChange
=
j
[
'time'
]
self
.
vFeedback
=
j
[
'v'
]
...
...
@@ -59,11 +60,11 @@ class relais:
if
self
.
timeLastStateConfirm
is
None
:
self
.
timeLastStateConfirm
=
time
.
time
()
self
.
state
=
rStates
.
confirmed
if
self
.
vFeedback
==
self
.
v
else
rStates
.
switching
self
.
publishCurrentStatus
(
reason
=
"relais feedback"
)
print
(
"Feedback Ende."
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"Feedback Ende."
)
self
.
printCurrentState
()
def
setV
(
self
,
v
,
t
=
None
,
reason
=
None
):
print
(
"New Value set to:"
,
v
,
"Old Value:"
,
self
.
v
,
"Relais:"
,
self
.
MQTTname
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"New Value set to:"
,
v
,
"Old Value:"
,
self
.
v
)
if
t
is
None
:
t
=
time
.
time
()
if
len
(
self
.
lockingPIRs
)
==
0
or
v
==
0
:
self
.
lightdesire
=
rLightDesire
.
stable
if
self
.
v
!=
v
:
# a change of output state
...
...
@@ -74,12 +75,12 @@ class relais:
retain
=
False
)
# send command to Relais
self
.
timeLastStateConfirm
=
t
self
.
publishCurrentStatus
(
t
,
reason
)
print
(
"setV Ende"
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"setV Ende"
)
def
checkAction
(
self
,
topic
,
msg
):
for
x
in
self
.
defaultTopics
:
# Normally the topics, which switches the relais on
if
topic
==
x
:
print
(
"Default Topic:"
,
topic
,
"msg:"
,
msg
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"Default Topic:"
,
topic
,
"msg:"
,
msg
)
if
msg
[
'type'
]
in
(
'TFBHSB55'
,
'FBH63'
):
# motion sensors
self
.
timeLastStateConfirm
=
time
.
time
()
if
msg
[
'v'
]
>
0
:
...
...
@@ -92,7 +93,7 @@ class relais:
self
.
lightdesire
=
rLightDesire
.
stable
self
.
timeLastStateConfirm
=
time
.
time
()
# to avoid immediate switch off after last PIR
self
.
publishCurrentStatus
(
reason
=
"last PIR sees no motion"
)
print
(
"Relais:"
,
self
.
MQTTname
,
"len(self.lockingPIRs)"
,
len
(
self
.
lockingPIRs
),
"self.lockingPIRs"
,
if
self
.
debug
:
print
(
self
.
MQTTname
,
"len(self.lockingPIRs)"
,
len
(
self
.
lockingPIRs
),
"self.lockingPIRs"
,
self
.
lockingPIRs
)
elif
msg
[
'type'
]
in
(
'FRW'
,
'FHF'
,
'FSM60B'
,
'FTK'
,
'FTKE'
):
# smoke detector, window handle, waterleak detector, magnet sensor, handle bar sensor
...
...
@@ -103,10 +104,10 @@ class relais:
elif
msg
[
'type'
]
==
"PTM215"
:
# switches
if
msg
[
'v'
]
>
0
:
self
.
setV
(
1
,
reason
=
"PTM215 pressed down, switch on"
)
# Switch on, if key pressed down
else
:
print
(
"Error: Type not supported for normal actions."
)
print
(
self
.
MQTTname
,
"Error: Type not supported for normal actions."
)
for
x
in
self
.
toggleTopics
:
# topics do a toggle of the relais
if
topic
==
x
:
print
(
"Toggle Topic:"
,
topic
,
"msg:"
,
msg
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"Toggle Topic:"
,
topic
,
"msg:"
,
msg
)
if
msg
[
'type'
]
==
"PTM215"
:
# switches
if
msg
[
'v'
]
>
0
:
# on key pressed down
if
self
.
v
==
0
:
...
...
@@ -114,43 +115,43 @@ class relais:
else
:
self
.
setV
(
0
,
reason
=
"PTM215 pressed down, toggle"
)
else
:
print
(
"Error: Type not supported for toggle."
)
print
(
self
.
MQTTname
,
"Error: Type not supported for toggle."
)
for
x
in
self
.
switchOffTopics
:
# topics switch off the relais
if
topic
==
x
:
print
(
"Switch Off Topic:"
,
topic
,
"msg:"
,
msg
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"Switch Off Topic:"
,
topic
,
"msg:"
,
msg
)
if
msg
[
'type'
]
==
"PTM215"
:
# switches
if
msg
[
'v'
]
>
0
:
self
.
setV
(
0
,
reason
=
"PTM pressed down, switch off"
)
# Switch Off, if key pressed down
else
:
print
(
"Error: Type not supported for switch off."
)
print
(
self
.
MQTTname
,
"Error: Type not supported for switch off."
)
for
x
in
self
.
inverseSwitchOnTopics
:
# topics switch on the relais, but inverted input
if
topic
==
x
:
print
(
"inverseSwitchOnTopics:"
,
topic
,
"msg:"
,
msg
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"inverseSwitchOnTopics:"
,
topic
,
"msg:"
,
msg
)
if
msg
[
'type'
]
in
(
'FRW'
,
'FHF'
,
'FSM60B'
,
'FTK'
,
'FTKE'
):
if
msg
[
'v'
]
==
0
:
self
.
setV
(
1
,
reason
=
"inverseSwitchOnTopics "
+
msg
[
'type'
])
# Switch on
else
:
print
(
"Error: Type not supported for inverseSwitchOnTopics."
)
print
(
self
.
MQTTname
,
"Error: Type not supported for inverseSwitchOnTopics."
)
def
printCurrentState
(
self
):
print
(
"Relais"
,
self
.
MQTTname
,
"v:"
,
self
.
v
,
self
.
state
,
self
.
lightdesire
,
"lockingPIRs:"
,
self
.
lockingPIRs
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"Relais"
,
self
.
MQTTname
,
"v:"
,
self
.
v
,
self
.
state
,
self
.
lightdesire
,
"lockingPIRs:"
,
self
.
lockingPIRs
)
def
check
(
self
):
if
self
.
lightdesire
==
rLightDesire
.
stable
and
self
.
state
!=
rStates
.
noFeedback
and
self
.
v
is
not
None
:
if
(
self
.
defaultSwitchOffTime
is
not
None
)
and
self
.
v
>
0
and
self
.
timeLastStateConfirm
+
self
.
defaultSwitchOffTime
<
time
.
time
():
# test for switch off
print
(
"Time up!"
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"Time up!"
)
self
.
setV
(
0
,
reason
=
"time up"
)
# switch off now
self
.
state
=
rLightDesire
.
stable
# no dimming etc. any longer
if
self
.
vFeedback
is
None
:
print
(
"No Feedback from Relais, yet: "
+
self
.
MQTTname
)
if
self
.
debug
:
print
(
self
.
MQTTname
,
"No Feedback from Relais yet."
)
else
:
t
=
time
.
time
()
if
self
.
v
!=
self
.
vFeedback
and
t
-
self
.
timeLastChange
>
10
and
t
-
self
.
timeFeedback
>
10
:
#if feedback state differs too long from desired state
print
(
"No OR wrong Feedback from Relais since last chance since more than 10 seconds."
)
print
(
self
.
MQTTname
,
"No OR wrong Feedback from Relais since last chance since more than 10 seconds."
)
self
.
v
=
self
.
vFeedback
self
.
timeLastChange
=
self
.
timeFeedback
self
.
timeLastStateConfirm
=
self
.
timeFeedback
self
.
state
=
rStates
.
noFeedback
self
.
printCurrentState
()
self
.
publishCurrentStatus
(
reason
=
"no feedback from relais"
)
self
.
publishCurrentStatus
(
reason
=
"no
or wrong
feedback from relais"
)
# test with:
# mosquitto_pub -t homie/fsr-ww/1 -m '{"setv": 0, "time": 1564251546.330417, "type": "FUD14", "v": 1}'
...
...
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