Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.bak
16 changes: 16 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/pycqa/pylint
rev: pylint-2.5.3
hooks:
- id: pylint
stages: [commit]
additional_dependencies: [pylint-flask]
2 changes: 2 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[MESSAGES CONTROL]
enable=useless-suppression
222 changes: 175 additions & 47 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
# -*- coding: utf-8 -*-
import paho.mqtt.client as mqtt
from eventlet import Queue
from modules import cbpi, app, ActorBase
from modules.core.hardware import SensorActive
""" cbpi3 MQTT module for Actors and Sensors """
import json
import os, re, threading, time
from modules.core.props import Property
import os
import re
import threading
import time

import paho.mqtt.client as mqtt # pylint: disable=import-error

from eventlet import Queue # pylint: disable=import-error
from modules import cbpi, app, ActorBase # pylint: disable=import-error
from modules.core.hardware import SensorActive # pylint: disable=import-error
from modules.core.props import Property # pylint: disable=import-error

q = Queue()

def on_connect(client, userdata, flags, rc):
print("MQTT Connected" + str(rc))

class MQTTThread (threading.Thread):
def on_connect(_client, _userdata, _flags, return_code):
"""
MQTT on_connect callback
"""
print(("MQTT Connected code=" + str(return_code)))

def __init__(self,server,port,username,password,tls):

class MQTTThread(threading.Thread):
"""
MQTT Thread
"""
def __init__(self, server, port, username, password, tls): #pylint: disable=too-many-arguments
threading.Thread.__init__(self)
self.server = server
self.port = port
Expand All @@ -23,45 +36,143 @@ def __init__(self,server,port,username,password,tls):
self.tls = tls

client = None

def run(self):
self.client = mqtt.Client()
self.client.on_connect = on_connect

if self.username != "username" and self.password != "password":
self.client.username_pw_set(self.username, self.password)

if self.tls.lower() == 'true':
self.client.tls_set_context(context=None)

self.client.connect(str(self.server), int(self.port), 60)
self.client.loop_forever()


@cbpi.actor
class MQTTActor(ActorBase):
topic = Property.Text("Topic", configurable=True, default_value="", description="MQTT TOPIC")
def on(self, power=100):
self.api.cache["mqtt"].client.publish(self.topic, payload=json.dumps({"state": "on"}), qos=2, retain=True)
"""
MQTT Actor
"""
topic = Property.Text("Topic",
configurable=True,
default_value="",
description="MQTT TOPIC")

def on(self, # pylint: disable=invalid-name
power=100): # pylint: disable=unused-argument
"""
turn actor on
"""
self.api.cache["mqtt"].client.publish(self.topic,
payload=json.dumps(
{"state": "on"}),
qos=2,
retain=True)

def off(self): # pylint: disable=invalid-name
"""
turn actor off
"""
self.api.cache["mqtt"].client.publish(self.topic,
payload=json.dumps(
{"state": "off"}),
qos=2,
retain=True)

def off(self):
self.api.cache["mqtt"].client.publish(self.topic, payload=json.dumps({"state": "off"}), qos=2, retain=True)

@cbpi.actor
class ESPEasyMQTT(ActorBase):
topic = Property.Text("Topic", configurable=True, default_value="", description="MQTT TOPIC")
def on(self, power=100):
self.api.cache["mqtt"].client.publish(self.topic, payload=1, qos=2, retain=True)
"""
ESPEasy MQTT Actor
"""
topic = Property.Text("Topic",
configurable=True,
default_value="",
description="MQTT TOPIC")

def on(self, # pylint: disable=invalid-name
power=100): # pylint: disable=unused-argument
"""
turn actor on
"""
self.api.cache["mqtt"].client.publish(self.topic,
payload=1,
qos=2,
retain=True)

def off(self):
"""
turn actor off
"""
self.api.cache["mqtt"].client.publish(self.topic,
payload=0,
qos=2,
retain=True)


@cbpi.actor
class ESPHomeMQTT(ActorBase):
"""
ESPHome MQTT Actor
"""
topic = Property.Text("Topic",
configurable=True,
default_value="",
description="MQTT TOPIC")

def on(self, # pylint: disable=invalid-name
power=100): # pylint: disable=unused-argument
"""
turn actor on
"""
self.api.cache["mqtt"].client.publish(self.topic,
payload='ON',
qos=2,
retain=True)

def off(self):
self.api.cache["mqtt"].client.publish(self.topic, payload=0, qos=2, retain=True)
"""
turn actor off
"""
self.api.cache["mqtt"].client.publish(self.topic,
payload='OFF',
qos=2,
retain=True)


@cbpi.sensor
class MQTT_SENSOR(SensorActive):
a_topic = Property.Text("Topic", configurable=True, default_value="", description="MQTT TOPIC")
b_payload = Property.Text("Payload Dictioanry", configurable=True, default_value="", description="Where to find msg in patload, leave blank for raw payload")
c_unit = Property.Text("Unit", configurable=True, default_value="", description="Units to display")
class MQTTSensor(SensorActive):
"""
MQTT Sensor
"""
a_topic = Property.Text("Topic",
configurable=True,
default_value="",
description="MQTT TOPIC")
b_payload = Property.Text(
"Payload Dictioanry",
configurable=True,
default_value="",
description="Where to find msg in patload, leave blank for raw payload"
)
c_unit = Property.Text("Unit",
configurable=True,
default_value="",
description="Units to display")

last_value = None
unit = None
topic = None
payload_text = None


def init(self):
"""
init MQTT Sensor
"""
self.topic = self.a_topic
if self.b_payload == "":
self.payload_text = None
Expand All @@ -70,84 +181,101 @@ def init(self):
self.unit = self.c_unit[0:3]

SensorActive.init(self)
def on_message(client, userdata, msg):

def on_message(_client, _userdata, msg):
try:
print "payload " + msg.payload
print(("payload " + msg.payload))
json_data = json.loads(msg.payload)
#print json_data
val = json_data
if self.payload_text is not None:
for key in self.payload_text:
val = val.get(key, None)
#print val
if isinstance(val, (int, float, basestring)):
if isinstance(val, (int, float, str)):
q.put({"id": on_message.sensorid, "value": val})
except Exception as e:
print e
except AttributeError as exp:
print(exp)

on_message.sensorid = self.id
self.api.cache["mqtt"].client.subscribe(self.topic)
self.api.cache["mqtt"].client.message_callback_add(self.topic, on_message)

self.api.cache["mqtt"].client.message_callback_add(
self.topic, on_message)

def get_value(self):
"""
return last value and unit
"""
return {"value": self.last_value, "unit": self.unit}

def get_unit(self):
"""
return unit
"""
return self.unit

def stop(self):
"""
stop sensor
"""
self.api.cache["mqtt"].client.unsubscribe(self.topic)
SensorActive.stop(self)

def execute(self):
'''
Active sensor has to handle his own loop
:return:
:return:
'''
self.sleep(5)


@cbpi.initalizer(order=0)
def initMQTT(app):
def init_mqtt(app): # pylint: disable=redefined-outer-name
"""
init MQTT
"""

server = app.get_config_parameter("MQTT_SERVER",None)
server = app.get_config_parameter("MQTT_SERVER", None)
if server is None:
server = "localhost"
cbpi.add_config_parameter("MQTT_SERVER", "localhost", "text", "MQTT Server")
cbpi.add_config_parameter("MQTT_SERVER", "localhost", "text",
"MQTT Server")

port = app.get_config_parameter("MQTT_PORT", None)
if port is None:
port = "1883"
cbpi.add_config_parameter("MQTT_PORT", "1883", "text", "MQTT Sever Port")
cbpi.add_config_parameter("MQTT_PORT", "1883", "text",
"MQTT Sever Port")

username = app.get_config_parameter("MQTT_USERNAME", None)
if username is None:
username = "username"
cbpi.add_config_parameter("MQTT_USERNAME", "username", "text", "MQTT username")
cbpi.add_config_parameter("MQTT_USERNAME", "username", "text",
"MQTT username")

password = app.get_config_parameter("MQTT_PASSWORD", None)
if password is None:
password = "password"
cbpi.add_config_parameter("MQTT_PASSWORD", "password", "text", "MQTT password")
cbpi.add_config_parameter("MQTT_PASSWORD", "password", "text",
"MQTT password")

tls = app.get_config_parameter("MQTT_TLS", None)
if tls is None:
tls = "false"
cbpi.add_config_parameter("MQTT_TLS", "false", "text", "MQTT TLS")

app.cache["mqtt"] = MQTTThread(server,port,username, password, tls)
app.cache["mqtt"] = MQTTThread(server, port, username, password, tls)
app.cache["mqtt"].daemon = True
app.cache["mqtt"].start()

def mqtt_reader(api):
while True:
try:
m = q.get(timeout=0.1)
api.cache.get("sensors")[m.get("id")].instance.last_value = m.get("value")
api.receive_sensor_value(m.get("id"), m.get("value"))
except:
message = q.get(timeout=0.1)
api.cache.get("sensors")[message.get(
"id")].instance.last_value = message.get("value")
api.receive_sensor_value(message.get("id"), message.get("value"))
except AttributeError:
pass

cbpi.socketio.start_background_task(target=mqtt_reader, api=app)