import src.irulez.log as log from typing import List, Tuple logger = log.get_logger('dimmer_domain') class ButtonLow: def __init__(self, button_numbers: List[int], number_of_pins: int): self.button_numbers = button_numbers self.number_of_pins = number_of_pins def cleanup(self, button_pins: List[int]): for button_pin in button_pins: self.button_numbers.remove(button_pin) logger.debug( f"Button pin with number {button_pin} removed from list.") class PinWithIntervals: def __init__(self, pin: int, interval_values: List[int]): self.__pin = pin self.__interval_values = interval_values @property def pin(self) -> int: return self.__pin @property def interval_values(self) -> List[int]: return self.__interval_values
from flask import jsonify, make_response from flask_sqlalchemy import SQLAlchemy import uuid from werkzeug.security import generate_password_hash, check_password_hash import jwt import datetime from src.webservice.base import Base import src.irulez.log as log import src.irulez.configuration as configuration config = configuration.Configuration() webserverConfig = config.get_webserver_config() logger = log.get_logger('webserver_user') db = SQLAlchemy() Base.query = db.session.query_property() class User(Base): __tablename__ = 'tbl_Users' id = db.Column(db.Integer, primary_key=True) public_id = db.Column(db.String(50), unique=True) email = db.Column(db.String(50)) password = db.Column(db.String(80)) admin = db.Column(db.Boolean) refresh_token = db.Column(db.String(50)) group_id = db.Column(db.Integer, db.ForeignKey('tbl_Groups.id')) group = db.relationship('Group') last_login = db.Column(db.DateTime)
import smtplib import src.irulez.log as log import src.irulez.util as util from abc import ABC, abstractmethod logger = log.get_logger('mail_processor') class MailProcessor(ABC): @abstractmethod def send_mail(self, json_object) -> None: pass class AuthenticateSMTPProcessor(MailProcessor): def __init__(self, user: object, pwd: object, port: object, url: object): self.gmail_user = user self.gmail_pwd = pwd self._from = user self.port = port self.url = url def send_mail(self, payload: str) -> None: json_object = util.deserialize_json(payload) recipient = json_object['mails'] to = recipient if type(recipient) is list else [recipient] subject = json_object['subject'] body = json_object['message']
from typing import Dict, List import src.button._domain as irulez_domain import src.irulez.constants as constants import src.irulez.log as log import src.irulez.util as util import src.irulez.topic_factory as topic_factory logger = log.get_logger('button_mqtt_sender') class MqttSender: def __init__(self, client, arduinos: {}): self.client = client self.arduinos = arduinos def publish_relative_action( self, json_list: Dict[str, List[irulez_domain.IndividualAction]]): # for name in json_list: # topic_name = constants.arduinoTopic + '/' + name + '/' + constants.actionTopic # publish_topic = constants.arduinoTopic + '/' + constants.actionTopic + '/' + constants.relativeTopic # if json_list[name].delay != 0: # topic_name = topic_name + '/' + constants.relativeTopic # publish_topic = publish_topic + '/' + constants.timerTopic # # payload = util.serialize_json( # { # "name": name, # "topic": topic_name, # "on": json_list[name].pin_numbers_on, "off": json_list[name].pin_numbers_off, # "delay": json_list[name].delay})
import src.irulez.log as log import paho.mqtt.client as mqtt from src.irulez import configuration logger = log.get_logger('logger') def on_connect(connected_client, _, __, rc) -> None: """Callback function for when the mqtt client is connected.""" logger.info("Connected client with result code " + str(rc)) # Subscribe in on_connect callback to automatically re-subscribe if the connection was lost # Subscribe to all arduino hexnumber actions # '+' means single level wildcard. '#' means multi level wildcard. # See http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices logger.debug("Subscribing to Everything") connected_client.subscribe('#') def on_subscribe(_, __, mid, granted_qos) -> None: logger.debug("Subscribed: " + str(mid) + " " + str(granted_qos)) def on_message(_, __, msg) -> None: """Callback function for when a new message is received.""" logger.debug(f"Received message {msg.topic}: {msg.payload}") # Create client client = mqtt.Client()
import threading from typing import List, Dict, Optional from xmlrpc.server import SimpleXMLRPCServer import src.output_status.domain as domain import src.irulez.log as log import src.output_status.service_domain as service import src.irulez.util as util logger = log.get_logger('StatusServiceServer') class OutputServiceServer(service.Service): def __init__(self, arduinos: Dict[str, domain.Arduino], dimmer_light_values: Dict[int, domain.DimmerLightValue], url: object, port: object): self.arduinos = arduinos self.url = url self.port = port self.__dimmer_light_values = dimmer_light_values def connect(self) -> None: server = SimpleXMLRPCServer((self.url, self.port)) logger.info(f"Listening on port {self.port}...") server.register_function(self.get_arduino_pin_status, "arduino_pin_status") server.register_function(self.get_arduino_dim_pin_status, "arduino_pin_dim_status") server.register_function(self.get_arduino_status, "arduino_status") server.register_function(self.get_dimmer_light_value, "dimmer_light_value")
import paho.mqtt.client as mqtt import src.button._db import src.irulez.constants as constants import src.irulez.log as log import src.irulez.util as util from src.irulez import configuration logger = log.get_logger('virtual_IO_board') # TODO: update code to get_virtual_IO not dummy DB # Get database, dummy for now db = src.button._db.get_dummy_db() def on_connect(connected_client, _, __, rc) -> None: """Callback function for when the mqtt client is connected.""" logger.info("Connected client with result code " + str(rc)) # Subscribe in on_connect callback to automatically re-subscribe if the connection was lost # Subscribe to all arduino hexnumber actions # '+' means single level wildcard. '#' means multi level wildcard. # See http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices logger.debug("Subscribing to " + str(constants.iRulezTopic) + "/" + constants.virtual_IO_board_name + "/" + constants.actionTopic) connected_client.subscribe(constants.iRulezTopic + "/" + constants.virtual_IO_board_name + "/" + constants.actionTopic) def on_subscribe(_, __, mid, granted_qos) -> None: logger.debug("Subscribed: " + str(mid) + " " + str(granted_qos))
import src.button._factory as factory import paho.mqtt.client as mqtt import src.button._db import src.irulez.configuration as configuration import src.irulez.constants as constants import src.irulez.log as log import src.irulez.util as util logger = log.get_logger('dummy') # Get database, dummy for now logger.debug('Getting database') db = src.button._db.get_maria_db() factory = factory.ArduinoConfigFactory(db) # Get arduinos from database and store them in a dictionary # Key is the name of the arduino logger.debug('Creating arduinos') arduinos = {} for ard in factory.create_arduino_config().arduinos: arduinos[ard.name] = ard def on_connect(connected_client, _, __, rc) -> None: """Callback function for when the mqtt client is connected.""" logger.info("Connected client with result code " + str(rc)) # Subscribe in on_connect callback to automatically re-subscribe if the connection was lost # Subscribe to all arduino hexnumber actions # '+' means single level wildcard. '#' means multi level wildcard. # See http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices
from enum import IntEnum import src.irulez.util as util from abc import ABC, abstractmethod import src.irulez.log as log from datetime import time from typing import List, Dict, Optional import src.irulez.constants as constants from threading import Timer logger = log.get_logger('button_domain') class ArduinoPinType(IntEnum): """Represents the purpose of a pin on an arduino""" BUTTON = 1 OUTPUT = 2 DIMMER = 3 class ActionType(IntEnum): """Represents what should happen. Toggle --> Relay H <-> L, On --> Relay H, Off --> Relay L, Follow_Button --> when button pressed -> relay H, dimmer --> dimmer""" TOGGLE = 1 ON = 2 OFF = 3 FOLLOW_BUTTON = 4 ON_DIMMER = 5
import src.irulez.util as util import src.irulez.log as log import src.output_status.ServiceClient as ServiceClient from typing import List, Dict logger = log.get_logger('relative_converter_mqtt_sender') class MqttSender: def __init__(self, client, status_service: ServiceClient.StatusServiceClient): self.client = client self.status_service = status_service def publish_absolute_action(self, json_object: Dict[str, object], absolute: List[bool]): payload = util.convert_array_to_hex(absolute) topic = json_object['topic'] logger.debug(f"Publishing: {topic}/{payload}") self.client.publish(topic, payload, 0, False) def send_absolute_update(self, json_object: Dict[str, object]): # Accepts relative pins as input, converts them to absolute updates # Current implementation sends updates to all arduinos or none. begin_status = self.status_service.get_arduino_status( str(json_object['name'])) end_status = begin_status[:] # noinspection PyTypeChecker
from enum import IntEnum import src.irulez.util as util from abc import ABC import src.irulez.log as log import src.irulez.constants as constants from typing import List, Optional, Dict logger = log.get_logger('domain') class ArduinoPinType(IntEnum): """Represents the purpose of a pin on an arduino""" BUTTON = 1 OUTPUT = 2 DIMMER = 3 class Pin(ABC): """Represents a pin on an arduino""" def __init__(self, number: int, pin_type: ArduinoPinType): self.__number = number self.__pin_type = pin_type self.__state = 0 self.__direction = constants.dim_direction_up @property def state(self) -> bool: if self.__state > 0: return True return False
sys.path.append(str(Path(__file__).resolve().parents[2].resolve())) import src.button._factory as factory import paho.mqtt.client as mqtt import src.button._db import src.button._mqtt_sender as mqtt_sender import src.button._processors as button_processor import src.irulez.configuration as configuration import src.irulez.constants as constants import src.irulez.log as log import src.irulez.util as util import src.output_status.ServiceClient as ServiceClient import src.button._action_executor as action_executor logger = log.get_logger('button') # Get database, dummy for now logger.debug('Getting database') db = src.button._db.get_maria_db() factory = factory.ArduinoConfigFactory(db) # Connect config = configuration.Configuration() mqttConfig = config.get_mqtt_config() serviceConfig = config.get_service_client_config() # Get arduinos from database and store them in a dictionary # Key is the name of the arduino logger.debug('Creating arduinos') arduinos = {}
import src.irulez.log as log import src.timer.timer_domain as timer_domain from threading import Timer import src.irulez.constants as constants import uuid import src.timer.mqtt_sender as mqtt_sender import src.irulez.util as util logger = log.get_logger('timer_processor') class TimerProcessor: def __init__(self, sender: mqtt_sender.MqttSender): # key=guid (id from the timer), values=Python built-in timer (fires action) object= Treading.Timer self.PythonTimers = {} # key=guid (id from the timer), values=object contains data for execution of the timer object=timer_domain.Timer self.ActionTimers = {} self.__default_timers = {} self.sender = sender def process_default_timer_request(self, payload: str): json_object = util.deserialize_json(payload) topic = util.get_str_from_json_object(json_object, 'topic') delay = util.get_int_from_json_object(json_object, 'delay') payload = json_object['payload'] # create an id for new timer timer_id = uuid.uuid4() self.__default_timers[timer_id] = timer_domain.DefaultTimer( topic, payload)
import src.irulez.log as log import src.irulez.constants as constants import src.irulez.util as util import paho.mqtt.client as mqtt import src.irulez.configuration as configuration import src.timer.processor as timer_processor import src.timer.mqtt_sender as mqtt_sender logger = log.get_logger('timer') # Create client client = mqtt.Client() sender = mqtt_sender.MqttSender(client) TimeProcessor = timer_processor.TimerProcessor(sender) def on_connect(connected_client, _, __, rc) -> None: """Callback function for when the mqtt client is connected.""" logger.info("Connected client with result code " + str(rc)) # Subscribe in on_connect callback to automatically re-subscribe if the connection was lost # Subscribe to all arduino hexnumber actions # '+' means single level wildcard. '#' means multi level wildcard. # See http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices # When the button module sends a timed relay action to the relative converter module topic = "{0}/{1}/{2}/{3}".format(str(constants.iRulezTopic), str(constants.actionTopic), str(constants.relativeTopic), str(constants.timerTopic)) logger.debug("Subscribing to " + str(topic)) connected_client.subscribe(str(topic))
from typing import List, Dict import src.irulez.log as log from abc import ABC logger = log.get_logger('timer_domain') # todo: create abstract timer class Timer(ABC): def __init__(self, topic: str): self.topic = topic class IndividualAction: """Represents the actions on pins that have to happen on a single arduino""" def __init__(self, arduino_name: str, mqtt_topic: str, delay: int, pin_numbers_on: List[int], pin_numbers_off: List[int]): self.name = arduino_name self.topic = mqtt_topic self.delay = delay self.pin_numbers_on = pin_numbers_on self.pin_numbers_off = pin_numbers_off def add_pin_on(self, pin_number: int): self.pin_numbers_on.append(pin_number) def add_pin_off(self, pin_number: int): self.pin_numbers_off.append(pin_number) def has_values_on(self) -> bool:
import paho.mqtt.publish as publish import time import src.irulez.constants as constants import src.irulez.util as util import src.irulez.configuration as configuration import src.irulez.log as logger log = logger.get_logger("test_action") # Connect config = configuration.Configuration() mqttConfig = config.get_mqtt_config() databaseConfig = config.get_database_config() arduino = input("Arduino name? <[DEMO]|virtual_IO_Board> ") number_of_pin = input("Number of pins? <[16]|20> ") pin = input("Pin [9]") button_type = input("C: CLICK, L: [LOW], H: HIGH M : Multi-click ") if button_type == '': button_type = 'L' if arduino == '': arduino = "DEMO" if number_of_pin == '': number_of_pin = 16 if pin == '': pin = 9 pin_states = [0] * int(number_of_pin) pin_states_Release = [0] * int(number_of_pin)
import src.irulez.log as log import src.irulez.constants as constants import src.irulez.util as util import paho.mqtt.client as mqtt import src.irulez.configuration as configuration import src.dimmer.processor as dimmer_processor import src.dimmer.mqtt_sender as mqtt_sender import src.output_status.ServiceClient as ServiceClient logger = log.get_logger('dimmer Module') # Get config config = configuration.Configuration() mqttConfig = config.get_mqtt_config() serviceConfig = config.get_service_client_config() # Create client client = mqtt.Client() StatusService = ServiceClient.StatusServiceClient(serviceConfig['url'], serviceConfig['port']) sender = mqtt_sender.MqttSender(client) processor = dimmer_processor.DimmerActionProcessor(client, sender, StatusService) def on_connect(connected_client, _, __, rc) -> None: """Callback function for when the mqtt client is connected.""" logger.info("Connected client with result code " + str(rc)) # Subscribe in on_connect callback to automatically re-subscribe if the connection was lost # Subscribe to all arduino hexnumber actions # '+' means single level wildcard. '#' means multi level wildcard.
import src.irulez.constants as constants import src.irulez.log as log import src.irulez.util as util logger = log.get_logger('timer_mqtt_sender') class MqttSender: def __init__(self, client) -> None: self.client = client def publish_relative_action(self, individual_action) -> None: payload = \ util.serialize_json( {"name": individual_action.name, "topic": constants.iRulezTopic + '/' + individual_action.name + '/' + constants.actionTopic, "on": individual_action.pin_numbers_on, "off": individual_action.pin_numbers_off, "delay": individual_action.delay}) logger.debug(f"Publishing: {individual_action.topic}{payload}") self.client.publish(individual_action.topic, payload, 0, False) def publish_default_action(self, topic: str, payload: str) -> None: logger.debug(f"Publishing: {topic}{payload}") self.client.publish(topic, payload, 0, False)
import src.output_status.service_domain as service import xmlrpc.client from typing import List, Optional import src.irulez.log as log logger = log.get_logger('StatusServiceClient') class StatusServiceClient(service.Service): def __init__(self, url: str, port: int): self.url = url self.port = port def get_arduino_status(self, name: str) -> List[bool]: with xmlrpc.client.ServerProxy(f"http://{self.url}:{self.port}/") as proxy: status = proxy.arduino_status(name) logger.debug(f"status: {str(status)}") return status def get_arduino_pin_status(self, name: str, pin: int) -> bool: with xmlrpc.client.ServerProxy(f"http://{self.url}:{self.port}/") as proxy: status = proxy.arduino_pin_status(name, pin) logger.debug(f"status: {str(status)}") return status def get_arduino_dim_pin_status(self, name: str, pin: int) -> str: with xmlrpc.client.ServerProxy(f"http://{self.url}:{self.port}/") as proxy: status = proxy.arduino_pin_dim_status(name, pin) logger.debug(f"status: {str(status)}") return status
import src.irulez.constants as constants import src.irulez.log as log from typing import Optional from typing import List, Dict import json logger = log.get_logger('util') def is_arduino_topic(topic: str) -> bool: """Checks if the given topic is a topic of an arduino""" if topic is None: return False return topic.startswith(constants.iRulezTopic) def is_arduino_action_topic(topic: str) -> bool: """Checks if the given topic is an action topic for an arduino""" # Format arduino_number/action/something return is_arduino_topic(topic) and '/' + constants.actionTopic in topic def is_arduino_dim_action_topic(topic: str) -> bool: """Checks if the given topic is a dim action topic for an arduino""" # Format arduino_number/dimAction/something return is_arduino_topic(topic) and '/' + constants.dimAction in topic def is_irulez_event_topic(topic: str) -> bool: """Checks if the given topic is an event topic of iRulez""" return is_arduino_topic(topic) and '/' + constants.eventTopic in topic
from typing import Dict, Optional import src.output_status.db_domain as db_domain import src.button._db as db import src.irulez.log as log import src.output_status.domain as domain logger = log.get_logger('factory') class ArduinoConfigFactory: def __init__(self, database: db.DbBase): self.__database = database def create_arduino_config(self) -> domain.ArduinoConfig: # Retrieve the whole universe from the database logger.debug('Retrieving arduinos from database') arduinos = self.__database.get_arduinos() logger.debug('Retrieving templates from database') templates = self.__database.get_templates() logger.debug('Retrieving output pins from database') output_pins = self.__database.get_output_pins() logger.info("Got all data from database") # Map templates mapped_templates = dict() for template in templates: mapped_templates[template.id] = template
import src.relative_convertor.mqtt_sender as mqtt_sender import src.irulez.log as log import src.irulez.util as util logger = log.get_logger('absolute_update_processor') class RelativeActionProcessor: def __init__(self, sender: mqtt_sender.MqttSender): self.sender = sender def process_relative_action_message(self, payload: str): logger.info("Processing " + payload) json_object = util.deserialize_json(payload) self.sender.send_absolute_update(json_object)
import src.dimmer.mqtt_sender as mqtt_sender import paho.mqtt.client as mqtt import src.irulez.log as log import src.irulez.constants as constants import src.irulez.util as util import src.dimmer.domain as domain from typing import List import src.output_status.ServiceClient as ServiceClient import uuid import math logger = log.get_logger('dimmer_processor') class DimmerActionProcessor: def __init__(self, client: mqtt.Client, sender: mqtt_sender.MqttSender, status_service: ServiceClient): self.__sender = sender self.__client = client self.__status_service = status_service # Dictionary with as key a uuid and value a domain.DimmingAction self.__dimming_actions = {} # Dictionary with as key a button_key and value a uuid (representing the dimming action id) # Button_key is a combination of arduino name and button number self.__button_cancel_action = {} def process_dimmer_message(self, payload: str): logger.info("Processing " + payload) json_object = util.deserialize_json(payload) # Payload info # "name --> arduino name"
import src.button._mqtt_sender as mqtt_sender import src.button._domain as domain from typing import Dict, List import src.irulez.log as log from datetime import datetime import src.output_status.ServiceClient as ServiceClient import src.irulez.util as util logger = log.get_logger('button_processor') class ActionExecutor: """ Contains logic for executing all kinds of actions """ def __init__(self, sender: mqtt_sender.MqttSender, status_service: ServiceClient.StatusServiceClient): self.__sender = sender self.__status_service = status_service def check_condition(self, condition: domain.Condition): if condition is None: return True if condition.condition_type == domain.ConditionType.TIME and isinstance(condition, domain.TimeCondition): return condition.from_time <= datetime.now().time() <= condition.to_time elif condition.condition_type == domain.ConditionType.OUTPUT_PIN and \ isinstance(condition, domain.OutputPinCondition): return condition.status == self.__status_service.get_arduino_pin_status(condition.output_pin.parent, condition.output_pin.number) elif condition.condition_type == domain.ConditionType.LIST and isinstance(condition, domain.ConditionList): for condition in condition.conditions:
import src.irulez.log as log import src.irulez.constants as constants import src.irulez.util as util import paho.mqtt.client as mqtt import src.irulez.configuration as configuration import src.relative_convertor.processors as relative_processor import src.relative_convertor.mqtt_sender as mqtt_sender import src.output_status.ServiceClient as ServiceClient logger = log.get_logger('absolute_update') # Get config config = configuration.Configuration() mqttConfig = config.get_mqtt_config() serviceConfig = config.get_service_client_config() # Create client client = mqtt.Client() StatusService = ServiceClient.StatusServiceClient(serviceConfig['url'], serviceConfig['port']) sender = mqtt_sender.MqttSender(client, StatusService) relative_action_processor = relative_processor.RelativeActionProcessor(sender) def on_connect(connected_client, _, __, rc) -> None: """Callback function for when the mqtt client is connected.""" logger.info("Connected client with result code " + str(rc)) # Subscribe in on_connect callback to automatically re-subscribe if the connection was lost # Subscribe to all arduino hexnumber actions # '+' means single level wildcard. '#' means multi level wildcard. # See http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices
import src.irulez.log as log import paho.mqtt.client as mqtt import src.irulez.constants as constants import src.output_status.db as db import src.irulez.util as util import src.irulez.topic_factory as topic_factory import src.output_status.processors as service_processor import src.irulez.configuration as configuration import src.output_status.factory as factory import src.output_status.ServiceServer as ServiceServer logger = log.get_logger('Service') # Get database, dummy for now logger.debug('Getting database') db = db.get_maria_db() factory = factory.ArduinoConfigFactory(db) # Get arduinos from database and store them in a dictionary # Key is the name of the arduino logger.debug('Creating arduinos') arduinos = {} for arduino in factory.create_arduino_config().arduinos: arduinos[arduino.name] = arduino dimmer_light_values = {} # Create client client = mqtt.Client() update_processor = service_processor.ServiceProcessor(arduinos, dimmer_light_values)
import src.irulez.util as util import src.irulez.topic_factory as topic_factory import src.irulez.log as log import paho.mqtt.client as mqtt import uuid logger = log.get_logger('dimmer_mqtt_sender') class MqttSender: def __init__(self, client: mqtt.Client): self.__client = client def publish_dimming_action_to_timer(self, dimming_action_id: uuid.UUID, delay: int): publish_topic = topic_factory.create_timer_dimmer_timer_fired_topic() topic_name = topic_factory.create_timer_dimmer_timer_fired_response_topic( ) payload = util.serialize_json({ 'topic': topic_name, 'payload': str(dimming_action_id), 'delay': delay }) logger.debug(f"Publishing: {publish_topic}{payload}") self.__client.publish(publish_topic, payload, 0, False) def publish_dimming_action_to_arduino(self, arduino_name: str, pin_number: int, dim_value: int): publish_topic = topic_factory.create_arduino_dim_action_topic( arduino_name, pin_number)
import paho.mqtt.client as mqtt import src.irulez.configuration as configuration import src.irulez.constants as constants import src.irulez.log as log import src.notification.processor as processor logger = log.get_logger('mail') # Create client client = mqtt.Client() config = configuration.Configuration() mailConfig = config.authenticate_SMTP_config() # Create gmail Processor mail = processor.AuthenticateSMTPProcessor(mailConfig['username'], mailConfig['password'], int(mailConfig['port']), mailConfig['url']) def on_connect(connected_client, _, __, rc) -> None: """Callback function for when the mqtt client is connected.""" logger.info("Connected client with result code " + str(rc)) # Subscribe in on_connect callback to automatically re-subscribe if the connection was lost # Subscribe to all arduino hexnumber actions # '+' means single level wildcard. '#' means multi level wildcard. # See http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices topic = str(constants.iRulezTopic) + "/" + str( constants.notificationTopic) + "/" + str(constants.mailTopic) logger.debug("Subscribing to " + str(topic))