initial push

This commit is contained in:
2020-07-06 23:41:26 +02:00
parent 595a577232
commit f1378361ee
233 changed files with 19916 additions and 1 deletions

View File

View File

@@ -0,0 +1,177 @@
import datetime
import time
import sys
import echo_serial.serial_controller as EchoSerial
import echo_db.database as EchoDB
import _thread
class AirConditioner:
@staticmethod
def handle_action(device, action, data):
actionData = device['actions'][action]
collection = EchoDB.EchoDB.database['Devices']
# Check if a thread is using the blinds, if so return.
if device['status'] == "busy":
return {'status': 'failed', 'message': 'Air Conditioner is being controlled by Echo, Please wait till finished.'}, 200
if action == "on":
if device['status'] == "on":
return {'status': 'failed', 'message': 'Air conditioning is already on!'}, 200
# Update Database
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'on' }})
EchoSerial.EchoSerial.send_commmand(device, "power")
return {'status': 'success', 'message': actionData['message']}, 200
if action == "off":
if device['status'] == "off":
return {'status': 'failed', 'message': 'Air conditioning is already off!'}, 200
EchoSerial.EchoSerial.send_commmand(device, "power")
# Update Database
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'off' }})
return {'status': 'success', 'message': actionData['message']}, 200
if action == "set_fan_speed":
selected_speed = data
if selected_speed == {}:
return {'status': 'failed', 'message': 'Please select a speed!'}, 200
if selected_speed == device['fan_speed']:
return {'status': 'failed', 'message': 'Fan speed already set to requested speed!'}, 200
if device['status'] == "off":
return {'status': 'failed', 'message': 'Air Conditioner must be on to change fan speeds!'}, 200
EchoSerial.EchoSerial.send_commmand(device, "fanspeed")
if device['fan_speed'] == "low":
# We just put the speed to high
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'fan_speed': 'high' }})
if device['fan_speed'] == "high":
# We just put the speed to high
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'fan_speed': 'low' }})
return {'status': 'success', 'message': actionData['message']}, 200
if action == "set_mode":
selected_mode = data
if selected_mode == {}:
return {'status': 'failed', 'message': 'Please select a mode!'}, 200
if device['status'] == "off":
return {'status': 'failed', 'message': 'Air Conditioniner must be on to change modes!'}, 200
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'busy' }})
# Start thread because this action has waiting functions
_thread.start_new_thread(AirConditioner.handleSetMode, ("Main Handle Set Mode Thread", 2, device, selected_mode))
return {'status': 'success', 'message': actionData['message']}, 200
if action == "set_temperature":
selected_temperature = data
if selected_temperature == {}:
return {'status': 'failed', 'message': 'Please select a temperature!'}, 200
if device['status'] == "off":
return {'status': 'failed', 'message': 'Air Conditioning must be on to change target temperatures!'}, 200
new_selected_temperature = int(selected_temperature)
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'busy' }})
# Start thread because this action has waiting functions
_thread.start_new_thread(AirConditioner.handleSetTemperature, ("Main Handle Set Temperature Thread", 2, device, new_selected_temperature))
return {'status': 'success', 'message': actionData['message']}, 200
@staticmethod
def handleSetTemperature(threadName, delay, device, temperature):
print('Started Air Conditioner Set Termperature Thread!')
if device['target_temperature'] == temperature:
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'on' }})
print('Exiting Air Conditioner Set Termperature Thread!')
sys.exit()
if temperature > device['target_temperature']:
temperature_direction = "up"
new_temperature_degrees = temperature - device['target_temperature']
if temperature < device['target_temperature']:
temperature_direction = "down"
new_temperature_degrees = device['target_temperature'] - temperature
# Plus one to init temp change on ac
for x in range(new_temperature_degrees + 1):
EchoSerial.EchoSerial.send_commmand(device, temperature_direction)
time.sleep(.3)
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'on', 'target_temperature': temperature }})
print('Exiting Air Conditioner Set Termperature Thread!')
@staticmethod
def handleSetMode(threadName, delay, device, mode):
print('Started Air Conditioner Set Mode Thread!')
if device['mode'] == mode:
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'on' }})
print('Exiting Air Conditioner Set Mode Thread!')
sys.exit()
# Goto base Pos (cooling)
if device['mode'] == "cooling":
#Do nothing, already in cooling mode (base pos)
pass
if device['mode'] == "dehumidifying":
# switch 2 times
EchoSerial.EchoSerial.send_commmand(device, "mode")
time.sleep(.3)
EchoSerial.EchoSerial.send_commmand(device, "mode")
time.sleep(.3)
if device['mode'] == "blowing":
# switch 1 time
EchoSerial.EchoSerial.send_commmand(device, "mode")
time.sleep(.3)
# Do nothing, base pos is cooling
if mode == "cooling":
pass
if mode == "dehumidifying":
# switch 1 time
EchoSerial.EchoSerial.send_commmand(device, "mode")
time.sleep(.3)
if mode == "blowing":
# switch 2 times
EchoSerial.EchoSerial.send_commmand(device, "mode")
time.sleep(.3)
EchoSerial.EchoSerial.send_commmand(device, "mode")
time.sleep(.3)
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'on', 'mode': mode }})
print('Exiting Air Conditioner Set Mode Thread!')

View File

@@ -0,0 +1,161 @@
import datetime
import time
import sys
import echo_serial.serial_controller as EchoSerial
import echo_db.database as EchoDB
import _thread
class Blinds:
@staticmethod
def handle_action(device, action, data):
actionData = device['actions'][action]
# Check if we send action too fast after last issued action
actionNow = datetime.datetime.now()
actionLast = device['last_used']
lastIssued = (actionNow - actionLast).total_seconds()
if lastIssued < 2.0:
return {'status': 'failed', 'message': 'Issued action too fast after last issued action!'}, 200
# Check if a thread is using the blinds, if so return.
if device['status'] == "busy":
return {'status': 'failed', 'message': 'Blinds are being controlled by Echo, Please wait till finished.'}, 200
# Check if we issued stop command and check if we are moving
# Stop blinds if we are moving
if action == "stop":
if device['status'] == "go_down" or device['status'] == "go_up":
return Blinds.stopActiveBlinds(device, action, data)
else:
return {'status': 'failed', 'message': 'Blinds are not moving!'}, 200
# Check if we are already going up or down
# If we are, stop that action
if device['status'] == "go_down" or device['status'] == "go_up":
return Blinds.stopActiveBlinds(device, action, data)
# If we are requesting specific preset
if action == "preset":
selected_preset = data
if selected_preset == {}:
return {'status': 'failed', 'message': 'Please select a preset!'}, 200
if selected_preset not in device['presets']:
return {'status': 'failed', 'message': 'Preset does not exist!'}, 200
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'busy' }})
# Start thread because this action has waiting functions
_thread.start_new_thread(Blinds.handleBlindsPreset, ("Main Serial Thread", 2, device, selected_preset))
return {'status': 'success', 'message': actionData['message']}, 200
# If we are requesting action
if action == "up" or action == "down":
# Send Serial Command
EchoSerial.EchoSerial.send_commmand(device, action)
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'go_' + action }})
return {'status': 'success', 'message': actionData['message']}, 200
# If we are requesting to set automatic time
if action == "set_automatic_time":
selected_auto_time = data
if selected_auto_time == {}:
return {'status': 'failed', 'message': 'Please select a time!'}, 200
if selected_auto_time == "--:--":
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'automatic_open': False, 'automatic_open_time': '--:--' }})
else:
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'automatic_open': True, 'automatic_open_time': selected_auto_time }})
return {'status': 'success', 'message': actionData['message']}, 200
@staticmethod
def stopActiveBlinds(device, action, data):
if device['status'] == "go_down":
EchoSerial.EchoSerial.send_commmand(device, "down")
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'custom' }})
return {'status': 'success', 'message': 'Stopped blinds.'}, 200
if device['status'] == "go_up":
EchoSerial.EchoSerial.send_commmand(device, "up")
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'custom' }})
return {'status': 'success', 'message': 'Stopped blinds.'}, 200
@staticmethod
def handleBlindsPreset(threadname, delay, device, preset):
print('Started Blinds Preset Thread!')
presetData = device['presets'][preset]
# Check if we are already in preset position
if device['status'] == "preset":
if device['current_preset'] == preset:
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'custom' }})
print('Exiting Blinds Preset Thread!')
sys.exit()
# If custom goto open position
if device['status'] == "custom":
Blinds.setBlindsOpen(device)
# If device is already in preset position, check if we need to go to open position first
# Or if we can skip that
if device['status'] == "preset":
if device['current_preset'] != "open":
Blinds.setBlindsOpen(device)
if preset == "closed_ventilated":
# Go down for 11 seconds
EchoSerial.EchoSerial.send_commmand(device, 'down')
time.sleep(17)
EchoSerial.EchoSerial.send_commmand(device, 'down')
if preset == "open_ventilated":
# Go down for 11 seconds
EchoSerial.EchoSerial.send_commmand(device, 'down')
time.sleep(11)
EchoSerial.EchoSerial.send_commmand(device, 'down')
if preset == "open":
# We already went to open position, no need to do it again
pass
if preset == "closed":
EchoSerial.EchoSerial.send_commmand(device, 'down')
time.sleep(19)
EchoSerial.EchoSerial.send_commmand(device, 'down')
# Update Database
collection = EchoDB.EchoDB.database['Devices']
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': 'preset', 'current_preset': preset }})
print('Exiting Blinds Preset Thread!')
@staticmethod
def setBlindsOpen(device):
EchoSerial.EchoSerial.send_commmand(device, 'up')
time.sleep(25)
EchoSerial.EchoSerial.send_commmand(device, 'up')
time.sleep(2)

View File

@@ -0,0 +1,31 @@
import echo_controller.switch as Switch
import echo_controller.sensor as Sensor
import echo_controller.blinds as Blinds
import echo_controller.air_conditioner as AirConditioner
import echo_controller.led_strip as LedStrip
class Controller:
# These are all the device types with actions
device_action_controls = {
'switch' : Switch.Switch.handle_action,
'sensor' : Sensor.Sensor.handle_action,
'blinds' : Blinds.Blinds.handle_action,
'airconditioner' : AirConditioner.AirConditioner.handle_action,
'led_strip': LedStrip.LEDStrip.handle_action
}
# These are all the output devices
device_output_controls = {
'sensor' : Sensor.Sensor.handle_data
}
@staticmethod
def handle_action(device, action, data = {}):
device_type = device['type']
return Controller.device_action_controls[device_type](device, action, data)
@staticmethod
def handle_output_device(device, action, data):
device_type = device['type']
return Controller.device_output_controls[device_type](device, action, data)

View File

@@ -0,0 +1,75 @@
import datetime
import time
import sys
import echo_serial.serial_controller as EchoSerial
import echo_db.database as EchoDB
import _thread
class LEDStrip:
@staticmethod
def handle_action(device, action, data):
actionData = device['actions'][action]
collection = EchoDB.EchoDB.database['Devices']
# Check if we send action too fast after last issued action
actionNow = datetime.datetime.now()
actionLast = device['last_used']
lastIssued = (actionNow - actionLast).total_seconds()
# if lastIssued < 2.0:
# return {'status': 'failed', 'message': 'Issued action too fast after last issued action!'}, 200
# Check if a thread is using the blinds, if so return.
if device['status'] == "busy":
return {'status': 'failed', 'message': 'LED Strip is being controlled by Echo, Please wait till finished.'}, 200
# Stop blinds if we are moving
if action == "off":
EchoSerial.EchoSerial.send_commmand(device, 'clear_color')
# Update Database
collection.update_one({'uuid': device['uuid']}, {
"$set": { 'last_used': datetime.datetime.now(),
"status": action
}})
return {'status': 'success', 'message': actionData['message']}, 200
if action == "on":
EchoSerial.EchoSerial.send_commmand(device, 'set_color', device['current_color'])
# Update Database
collection.update_one({'uuid': device['uuid']}, {
"$set": { 'last_used': datetime.datetime.now(),
"status": action
}})
return {'status': 'success', 'message': actionData['message']}, 200
if action == "set_color":
EchoSerial.EchoSerial.send_commmand(device, 'clear_color', data)
# Update Database
collection.update_one({'uuid': device['uuid']}, {
"$set": { 'last_used': datetime.datetime.now(),
"current_color": data
}})
return {'status': 'success', 'message': actionData['message']}, 200
if action == "automatic_movement":
if data == "on":
# Update Database
now_time = datetime.datetime.now()
auto_shutdown = now_time + datetime.timedelta(minutes = 2)
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'automatic_movement': True, 'automatic_shutdown': auto_shutdown }})
return {'status': 'success', 'message': actionData['message']}, 200
if data == "off":
# Update Database
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'automatic_movement': False }})
return {'status': 'success', 'message': actionData['message']}, 200
return {'status': 'failed', 'message': 'Setting not found!'}, 200

View File

@@ -0,0 +1,105 @@
import datetime
import echo_serial.serial_controller as EchoSerial
import echo_db.database as EchoDB
from bson import json_util, ObjectId
import json
import echo_controller.switch as Switch
class Sensor:
@staticmethod
def handle_action(device, action, data):
actionData = device['actions'][action]
#
# Climate Sensors
#
if action == "gather_climate_data":
EchoSerial.EchoSerial.send_commmand(device, action)
return {'status': 'success', 'message': actionData['message']}, 200
if action == "get_climate_data":
collection = EchoDB.EchoDB.database['ClimateLogs']
data = collection.find().sort([('timestamp', -1)]).limit(1)
data_json = json.loads(json_util.dumps(data))
return {'status': 'success', 'message': actionData['message'], 'data': data_json}, 200
#
# Light Sensors
#
if action == "gather_light_data":
EchoSerial.EchoSerial.send_commmand(device, action)
return {'status': 'success', 'message': actionData['message']}, 200
if action == "get_light_data":
collection = EchoDB.EchoDB.database['LightLog']
data = collection.find().sort([('timestamp', -1)]).limit(1)
data_json = json.loads(json_util.dumps(data))
return {'status': 'success', 'message': actionData['message'], 'data': data_json}, 200
#
# Movement Sensors
#
if action == "get_movment_data":
collection = EchoDB.EchoDB.database['MovementLog']
data = collection.find().sort([('timestamp', -1)]).limit(20)
data_json = json.loads(json_util.dumps(data))
return {'status': 'success', 'message': actionData['message'], 'data': data_json}, 200
@staticmethod
def handle_data(device, action, data):
#
# Climate Sensors
#
if action == 'climate_data':
collection = EchoDB.EchoDB.database['ClimateLogs']
climate_data = data[2].split(',')
logData = {
'uuid': device['uuid'],
'temperature': float(climate_data[0]),
'humidity': float(climate_data[1]),
'timestamp': datetime.datetime.now()
}
collection.insert(logData)
#
# Light Sensors
#
if action == 'light_data':
collection = EchoDB.EchoDB.database['LightLog']
lightAmount = data[2]
logData = {
'uuid': device['uuid'],
'light_amount': int(lightAmount),
'timestamp': datetime.datetime.now()
}
collection.insert(logData)
#
# Movement Sensors
#
if action == 'movement_data':
collection = EchoDB.EchoDB.database['MovementLog']
typeMovement = data[2]
logData = {
'uuid': device['uuid'],
'type_movement': typeMovement,
'timestamp': datetime.datetime.now()
}
collection.insert(logData)
# Handle Automatic Lights
Switch.Switch.handle_movement_switch()

View File

@@ -0,0 +1,79 @@
import datetime
import echo_serial.serial_controller as EchoSerial
import echo_db.database as EchoDB
class Switch:
@staticmethod
def handle_action(device, action, data):
actionData = device['actions'][action]
collection = EchoDB.EchoDB.database['Devices']
if action == "automatic_movement":
if data == "on":
# Update Database
now_time = datetime.datetime.now()
auto_shutdown = now_time + datetime.timedelta(minutes= 2)
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'automatic_movement': True, 'automatic_shutdown': auto_shutdown }})
return {'status': 'success', 'message': actionData['message']}, 200
if data == "off":
# Update Database
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'automatic_movement': False }})
return {'status': 'success', 'message': actionData['message']}, 200
return {'status': 'failed', 'message': 'Setting not found!'}, 200
#Check if status is already the action
if device['status'] == action:
message = "Device is already in the requested state!"
return {'status': 'failed', 'message': message}, 200
# Send Serial Command
EchoSerial.EchoSerial.send_commmand(device, action)
# Update Database
collection.update_one({'uuid': device['uuid']}, {"$set": { 'last_used': datetime.datetime.now(), 'status': action }})
return {'status': 'success', 'message': actionData['message']}, 200
@staticmethod
def handle_movement_switch():
mainLightUUID = '9472-4f60'
collection = EchoDB.EchoDB.database['Devices']
# Get Device (Main Light)
mainLightDevice = collection.find_one({'uuid': mainLightUUID})
# Check if automatic movement mode of main light is enabled, else do nothing
if mainLightDevice['automatic_movement'] == False:
return
# Check if light levels are low enough to turn on light
collectionLight = EchoDB.EchoDB.database['LightLog']
data = collectionLight.find().sort([('timestamp', -1)]).limit(1)
if data[0]['light_amount'] > 250:
return;
# Light is already on, update automatic shutdown.
if mainLightDevice['status'] == "on":
now_time = datetime.datetime.now()
auto_shutdown = now_time + datetime.timedelta(minutes= 2)
collection.update_one({'uuid': mainLightUUID}, {"$set": { 'automatic_shutdown': auto_shutdown }})
return
# Light is off, turn it on
# Send Serial Command
EchoSerial.EchoSerial.send_commmand(mainLightDevice, "on")
# Auto shutdown time
now_time = datetime.datetime.now()
auto_shutdown = now_time + datetime.timedelta(minutes= 2)
# Update Database
collection.update_one({'uuid': mainLightUUID}, {"$set": { 'last_used': datetime.datetime.now(), 'status': "on", 'automatic_shutdown': auto_shutdown }})