Skip to content
Snippets Groups Projects
Commit c67c055f authored by Nizar Bouchedakh's avatar Nizar Bouchedakh
Browse files

Smart-building app

parents
No related branches found
No related tags found
No related merge requests found
Pipeline #
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import time
import logging
import configpi
from louie import dispatcher
from datetime import datetime
from flask import jsonify
from collections import OrderedDict
from openzwave.network import ZWaveNetwork
from openzwave.option import ZWaveOption
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('openzwave')
started = False
name = configpi.name
###########################################################################################################################
###########################################################################################################################
########## Root parent backend class ###############################################################################
###########################################################################################################################
###########################################################################################################################
class Backend():
def __init__(self):
################### instanciation de l'objet backend ########################################################
###### options needed for python openzwave library like config files path, logging,
device = configpi.interface
options = ZWaveOption(device, config_path="/home/pi/IoTLab/python-openzwave/openzwave/config", user_path=".", cmd_line="")
options.set_log_file("OZW.log")
options.set_append_log_file(False)
options.set_console_output(False)
options.set_save_log_level('Warning')
options.set_logging(True)
options.lock()
# creation of the object network using the options entity already created
self.network = ZWaveNetwork(options, autostart=False)
###### These dispatchers associate a method to a signal. the signals are generated by the library python-openzwave.
###### Once the signal is received. It's associated method is executed (see "_node_added" example below in "_network_started" method)
dispatcher.connect(self._network_started, ZWaveNetwork.SIGNAL_NETWORK_STARTED)
dispatcher.connect(self._network_ready, ZWaveNetwork.SIGNAL_NETWORK_READY)
###### backend object attributes
# self.devices = OrderedDict() ### will contain the list of nodes in the network
# self.sensors = OrderedDict() ### will contain the list of sensors (only) in the network
self.node_added = False
self.node_removed = False
self.timestamps = {} ### will contain the time of the last values' update for each sensor
self.queryStages = { ### the diffrent stages that a node object gets through before being ready
"None" : 1, # Query process hasn't started for this node
"ProtocolInfo" : 2, # Retrieve protocol information
"Probe" : 3, # Ping device to see if alive
"WakeUp" : 4, # Start wake up process if a sleeping node
"ManufacturerSpecific1" : 5, # Retrieve manufacturer name and product ids if ProtocolInfo lets us
"NodeInfo" : 6, # Retrieve info about supported, controlled command classes
"SecurityReport" : 7, # Retrieve a list of Command Classes that require Security
"ManufacturerSpecific2" : 8, # Retrieve manufacturer name and product ids
"Versions" : 9, # Retrieve version information
"Instances" : 10, # Retrieve information about multiple command class instances
"Static" : 11, # Retrieve static information (doesn't change)
"Probe1" : 12, # Ping a device upon starting with configuration
"Associations" : 13, # Retrieve information about associations
"Neighbors" : 14, # Retrieve node neighbor list
"Session" : 15, # Retrieve session information (changes infrequently)
"Dynamic" : 16, # Retrieve dynamic information (changes frequently)
"Configuration" : 17, # Retrieve configurable parameter information (only done on request)
"Complete" : 18 # Query process is completed for this node
}
#######################################################################################################################
############# LAUNCH #################################################################################################
#######################################################################################################################
def _network_started(self, network):
# executed once the software representation is started. the discovery of the network components has begun. they will be mapped into objects
print("network started - %d nodes were found." % network.nodes_count)
# these dispatchers associate a method to a signal. the signals are generated by the library python-openzwave.
# a signal may contain a number of parameters that are passed to the method associated to the signal.
# for exemple, the dispatcher below associates the signal "SIGNAL_NODE_ADDED" to the method "_node_added" that is implemented below (line 111).
# the signal "SIGNAL_NODE_ADDED" transports two parameters which are the objects network and node.
# once this signal is received, these two parameters will be passed to the method "_node_added" and the method will be executed.
dispatcher.connect(self._node_added, ZWaveNetwork.SIGNAL_NODE_ADDED)
dispatcher.connect(self._node_removed, ZWaveNetwork.SIGNAL_NODE_REMOVED)
def _network_ready(self, network):
# executed once the software representation is ready
print("network : ready : %d nodes were found." % network.nodes_count)
print("network : controller is : %s" % network.controller)
dispatcher.connect(self._value_update, ZWaveNetwork.SIGNAL_VALUE)
def _node_added(self, network, node):
# executed when node is added to the software representation. it's executed after the method "_debug_node_new" (see below)
print('node added: %s.' % node.node_id)
self.timestamps["timestamp" + str(node.node_id)] = "None"
self.node_added = True
def _node_removed(self, network, node):
# executed when node is removed from the software representation
print('node removed: %s.' % node.name)
self.node_removed = True
def _value_update(self, network, node, value):
# executed when a new value from a node is received
print('Node %s: value update: %s is %s.' % (node.node_id, value.label, value.data))
self.timestamps["timestamp" + str(node.node_id)] = int(time.time())
################################################################################################################
######################## START AND STOP THE SOFTWARE REPRESENTATION ############################################
################################################################################################################
def start(self):
# this method starts the software representation
global started
if started:
print "Already started"
return
started = True
self.network.start()
print "Z-Wave Network Starting..."
for i in range(0, 300):
if self.network.state == self.network.STATE_READY:
break
else:
time.sleep(1.0)
if not self.network.is_ready:
print "Network is not ready but continue anyway"
print "------------------------------------------------------------"
print "Nodes in network : %s" % self.network.nodes_count
print "------------------------------------------------------------"
def stop(self):
# this method stops the software representation
global started
started = False
print "Stopping Z-Wave Network... "
self.network.stop()
def reset(self):
if self.network.nodes_count == 1:
self.network.controller.hard_reset()
return "Hard Reset Done"
return "Cannot make Hard Reset while nodes included in network"
#########################################################################################################################
############## YOUR WORK STARTS HERE ####################################################################################
#########################################################################################################################
#########################################################################################################################
#######################################################################################################################
############# NETWORK #################################################################################################
#######################################################################################################################
def network_info(self):
#### COMPLETE THIS METHOD ##############
return "this method returns a JSON that lists all network nodes and gives some informations about each one of them like the ID, neighbors, ..."
#######################################################################################################################
############# NODES #################################################################################################
#######################################################################################################################
def ordered_nodes_dict(self):
# returns an ordered list of the network's nodes sorted by node's id
return OrderedDict(sorted(self.network.nodes.items()))
def addNode(self):
#### COMPLETE THIS METHOD ##############
return "this method passes the controller to inclusion mode and gets it out of it after 20 seconds "
def removeNode(self):
#### COMPLETE THIS METHOD ##############
return "this method passes the controller to exclusion mode and gets it out of it after 20 seconds "
def get_nodes_list(self):
#### COMPLETE THIS METHOD ##############
return "this method returns the list of nodes "
def set_node_location(self, n, value):
#### COMPLETE THIS METHOD ##############
return " this method sets the location of a specific sensor node"
def set_node_name(self, n, value):
#### COMPLETE THIS METHOD ##############
return "this method sets the name of a specific sensor node"
def get_node_location(self, n):
#### COMPLETE THIS METHOD ##############
return "this method gets the location of a specific sensor node"
def get_node_name(self, n):
#### COMPLETE THIS METHOD ##############
return "this method gets the name of a specific sensor node"
def get_neighbours_list(self, n):
#### COMPLETE THIS METHOD ##############
return "this method gets the list of neighbours of a specific sensor node"
def set_node_config_parameter(self, n, param, value, size):
#### COMPLETE THIS METHOD ##############
return "this method sets a configuration parameter to a given value"
def get_node_config_parameter(self, n, param):
#### COMPLETE THIS METHOD ##############
return "this method gets the value of a configuration parameter"
def get_nodes_Configuration(self):
#### COMPLETE THIS METHOD ##############
return "this method returns a JSON that gives an overview of the network and it's nodes' configuration parameters (like the ID, Wake-up Interval, Group 1 Reports, Group 1 Interval ...)"
#######################################################################################################################
############# Multisensors #################################################################################################
#######################################################################################################################
class Backend_with_sensors(Backend):
def get_sensors_list(self):
#### COMPLETE THIS METHOD ##############
return "this method returns the list of sensors"
def get_temperature(self, n):
#### HERE'S AN EXAMPLE OF A METHOD THAT GETS THE TEMPERATURE OF A SPECIFIC SENSOR NODE ##############
for node in self.network.nodes.itervalues():
if node.node_id == n and node.isReady and n != 1 and "timestamp"+str(node.node_id) in self.timestamps:
values = node.get_values(0x31, "User", "All", True, False)
for value in values.itervalues():
if value.label == "Temperature":
val = round(value.data,1)
# if len(node.location) < 3:
# node.location = configpi.sensors[str(node.node_id)][:4]
return jsonify(controller = name, sensor = node.node_id, location = node.location, type = value.label.lower(), updateTime = self.timestamps["timestamp"+str(node.node_id)], value = val)
return "Node not ready or wrong sensor node !"
def get_humidity(self, n):
#### HERE'S AN EXAMPLE OF A METHOD THAT GETS THE HUMIDITY OF A SPECIFIC SENSOR NODE ##############
for node in self.network.nodes.itervalues():
if node.node_id == n and node.isReady and n != 1 and "timestamp"+str(node.node_id) in self.timestamps:
values = node.get_values(0x31, "User", "All", True, False)
for value in values.itervalues():
if value.label == "Relative Humidity":
val = int(value.data)
# if len(node.location) < 3:
# node.location = configpi.sensors[str(node.node_id)][:4]
return jsonify(controller = name, sensor = node.node_id, location = node.location, type = value.label.lower(), updateTime = self.timestamps["timestamp"+str(node.node_id)], value = val)
return "Node not ready or wrong sensor node !"
def get_luminance(self, n):
#### COMPLETE THIS METHOD ##############
return "this method gets the luminance measure of a specific sensor node"
def get_motion(self, n):
#### COMPLETE THIS METHOD ##############
return "this method this method gets the motion measure of a specific sensor node"
def get_battery(self, n):
#### COMPLETE THIS METHOD ##############
return "this method this method gets the battery measure of a specific sensor node"
def get_all_Measures(self, n):
#### COMPLETE THIS METHOD ##############
return "this method gets all the measures of a specific sensor node"
def set_basic_nodes_configuration(self, Grp_interval, Grp_reports, Wakeup_interval):
#### COMPLETE THIS METHOD ##############
return "this method configures the nodes whit a specific configuration"
###########################################################################################################################
###########################################################################################################################
################## Dimmers class ##################################################################################
###########################################################################################################################
###########################################################################################################################
class Backend_with_dimmers(Backend):
def __init__(self):
Backend.__init__(self)
def get_dimmers(self):
#### COMPLETE THIS METHOD ##############
return "this method returns the list of dimmers"
def set_dimmer_level(self, n, level):
#### COMPLETE THIS METHOD ##############
return "this method sets a dimmer's brightness level of a specific node"
def get_dimmer_level(self, n):
#### COMPLETE THIS METHOD ##############
return "this method gets a dimmer's brightness level of a specific node"
###########################################################################################################################
###########################################################################################################################
########## Dimmers and multisensors class ######################################## #############################
###########################################################################################################################
###########################################################################################################################
class Backend_with_dimmers_and_sensors(Backend_with_dimmers, Backend_with_sensors): # Cette classe sera utilise dans "flask-main"
pass
name = 'Pi lab1'
location = 'lausanne'
interface = '/dev/ttyACM0' #/dev/ttyUSB0 ou /dev/ttyAMA0
#! /usr/bin/env python
#-*- coding: utf-8 -*-
import sys
import time
import logging
import configpi
import os
file_path = os.path.dirname(__file__)
sys.path.insert(0, file_path)
from flask import Flask, render_template, jsonify, Response, request
from backend import *
app = Flask(__name__)
backend = Backend_with_dimmers_and_sensors()
#######################################################################################################################
############# INDEX PAGE ##############################################################################################
#######################################################################################################################
@app.route('/', strict_slashes=False)
def index():
# returns a html page with a list of routes
return render_template("index.html", title=configpi.name)
#######################################################################################################################
############# NETWORK #################################################################################################
#######################################################################################################################
"""
@api {get} /network/info get_network_info
@apiName get_network_info
@apiGroup Network
@apiSuccess {String} Network_Home_ID Network's ID
@apiSuccess {JSON} Node_<Number> A JSON containing node's information (for each node). See below
@apiSuccess {boolean} Is_Ready Node status
@apiSuccess {String[]} Neighbours Node's neighbours
@apiSuccess {Number} Node_ID Node's ID
@apiSuccess {String} Node_location Node's location
@apiSuccess {String} Node_name Node's name
@apiSuccess {String} Product_name Node's product name
@apiSuccess {String} Query_stage Query Stage
@apiSuccess {Number} Query_stage_(%) Query Stage (percentage)
@apiSuccessExample {json} Example of result in case of success:
{
"Network Home ID": "0xe221b13f",
"Node 1": {
"Is Ready": true,
"Neighbours": "2",
"Node ID": "1",
"Node location": "",
"Node name": "",
"Product name": "Z-Stick Gen5",
"Query Stage": "Complete",
"Query Stage (%)": "100 %"
},
"Node 2": {
"Is Ready": true,
"Neighbours": "1",
"Node ID": "2",
"Node location": "",
"Node name": "",
"Product name": "MultiSensor 6",
"Query Stage": "Complete",
"Query Stage (%)": "100 %"
}
}
@apiDescription Gets information about the Z-Wave network in a JSON format
"""
@app.route('/network/info', strict_slashes=False)
def network_info():
return backend.network_info()
"""
@api {post} /network/set_nodes_basic_configuration set_nodes_basic_configuration
@apiName set_nodes_basic_configuration
@apiGroup Network
@apiParam {Number} Group_Interval Number of seconds between two successive transfers of measures
@apiParam {Number} Group_Reports Number identifying measures sent by the sensor
@apiParam {Number} Wake-up_Interval Number of seconds between two node's wake-ups
@apiParamExample {json} Request-Exemple :
{
'Group_Interval' : '241',
'Group_Reports' : '480',
'Wake-up_Interval' : '480'
}
@apiSuccess {String} Message Description of the new nodes' configuration.
@apiDescription Configure all nodes of the network with a predefined configuration. This methods configures only Group 1. All measurements (temperature, luminosity, motion and humidity) must be retrieved from the sensors after a given period of time (Group_Interval Number).
"""
@app.route('/network/set_nodes_basic_configuration', methods=['GET','POST'], strict_slashes=False)
def network_configureNodes():
# configure all the nodes of the network with a specific configuration
if request.method=='POST':
content = request.get_json()
if all(item in content.keys() for item in ['Group_Interval','Group_Reports','Wake-up_Interval']):
Grp_interval = int(content['Group_Interval'])
Grp_reports = int(content['Group_Reports'])
Wakeup_interval = int(content['Wake-up_Interval'])
return backend.set_basic_nodes_configuration(Grp_interval,Grp_reports,Wakeup_interval)
return 'wrong input'
return 'use POST method'
"""
@api {get} /network/get_nodes_configuration get_nodes_configuration
@apiName get_nodes_configuration
@apiGroup Network
@apiSuccess {String} Network_Home_ID Network's ID
@apiSuccess {JSON} Node_<Number> A JSON containing node's informations that are detailed above (for each node except the controller)
@apiSuccess {String} Enable_Motion_Sensor Motion sensor level
@apiSuccess {Number} Group1_Interval Number of seconds between two Group1 measurements transmissions
@apiSuccess {Number} Group1_Reports A number specifying measurements sent in this group (set to 241 to send all measurements on this group)
@apiSuccess {Number} Group2_Interval Number of seconds between two Group2 measurements transmissions
@apiSuccess {Number} Group2_Reports A number specifying measurements sent in this group (set to 0 because no measurements will be sent on this group)
@apiSuccess {Number} Group3_Interval Number of seconds between two Group3 measurements transmissions
@apiSuccess {Number} Group3_Reports A number specifying measurements sent in this group (set to 0 because no measurements will be sent on this group)
@apiSuccess {Number} Node_ID Node's ID
@apiSuccess {Number} Wake_up_Interval Number of seconds between two wake-ups
@apiSuccessExample {json} Example of result in case of success:
{
"Network Home ID": "0xe221b13f",
"Node 2": {
"Enable Motion Sensor": "Enabled level 5 (maximum sensitivity",
"Group 1 Interval": "3600",
"Group 1 Reports": "241",
"Group 2 Interval": "3600",
"Group 2 Reports": "0",
"Group 3 Interval": "3600",
"Group 3 Reports": "0",
"Node ID": "2",
"Wake-up Interval": "3600"
}
}
@apiDescription Gets the list of nodes and their configuration parameters in a JSON format. For each node, the system should provide the following information: Node ID, Motion sensor level, Wake_up_Interval and the report and interval of each group (there are three groups). See details in the documentation of the sensor: Aeon Labs MultiSensor 6 (Z-wave MultiSensor).
"""
@app.route('/network/get_nodes_configuration', strict_slashes=False)
def get_nodes_Configuration():
# gets a html with the list of nodes with their config parameters
return backend.get_nodes_Configuration() ######## a revoir
"""
@api {get} /network/start start_network
@apiName start_network
@apiGroup Network
@apiSuccess {String} Message Confirmation that the Z-Wave Network Restarted
@apiDescription Starts the openzwave software representation of the network
"""
@app.route('/network/start', strict_slashes=False)
def start():
# start software representation
backend.start()
return "Z-Wave Network Started"
"""
@api {get} /network/stop stop_netowrk
@apiName stop_netowrk
@apiGroup Network
@apiSuccess {String} Message Confirmation that the Z-Wave Network has stopped
@apiDescription Stops the openzwave software representation of the network
"""
@app.route('/network/stop', strict_slashes=False)
def stop():
# stop the software representation
backend.stop()
time.sleep(2)
return "Z-Wave Network Stopped"
"""
@api {get} /network/reset reset_network
@apiName Reset Network
@apiGroup Network
@apiSuccess {String} Message Confirmation that the Z-Wave Network has been reset
@apiDescription Resets the network's controller. Do not call this method before excluding (removing) the sensors connected to the controller.
"""
@app.route('/network/reset', strict_slashes=False)
def reset():
# restart software representation
backend.reset()
return "Z-Wave Network Reset"
######################################################################################################################
############# NODES ##################################################################################################
######################################################################################################################
### THESE METHODS ARE SPECIALLY MADE FOR ALL TYPES OF NODES ##########################################################
######################################################################################################################
"""
@api {get} /nodes/get_nodes_list get_nodes_list
@apiName get_nodes_list
@apiGroup Nodes
@apiSuccess {String[]} JSON List of all nodes in the network in a JSON format
@apiDescription Lists all nodes in the network
"""
@app.route('/nodes/get_nodes_list', strict_slashes=False)
def nodes():
# gets a list of all nodes in the network in a JSON format
return backend.get_nodes_list()
"""
@api {put} /nodes/add_node add_node
@apiName add_node
@apiGroup Nodes
@apiSuccess {String} Message Node added successfully
@apiDescription Adds Node to the network by getting the controller into inclusion mode for 20 seconds. The node can not be a controller.
"""
@app.route('/nodes/add_node', methods=['PUT'], strict_slashes=False)
def add_node():
# passes controller to inclusion mode
return backend.addNode()
"""
@api {put} /nodes/remove_node remove_node
@apiName remove_node
@apiGroup Nodes
@apiSuccess {String} Message Node removed successfully
@apiDescription Removes Node from the network by getting the controller into exclusion mode for 20 seconds
"""
@app.route('/nodes/remove_node', methods=['PUT'], strict_slashes=False)
def remove_node():
# passes controller to exclusion mode
return backend.removeNode()
"""
@api {post} /nodes/set_parameter set_parameter
@apiName set_parameter
@apiGroup Nodes
@apiParam {Number} node_id Sensor's unique ID
@apiParam {Number} parameter_index Parameter's unique index (See sensor manual)
@apiParam {Number} value new value of the parameter
@apiParam {Number} size size of value of the parameter (See sensor manual)
@apiParamExample {json} Request-Exemple :
{
'node_id' : '4',
'parameter_index' : '101',
'value' : '227',
'size' : '4'
}
@apiSuccess {String} parameter parameter's new value
@apiDescription Sets the value of a given parameter of a node
"""
@app.route('/nodes/set_parameter', methods=['GET', 'POST'],strict_slashes=False)
def set_config_param():
# sets a config parameter of a sensor node
if request.method=='POST':
content = request.get_json()
if all(item in content.keys() for item in ['node_id','parameter_index','value','size']):
node = int(content['node_id'])
param = int(content['parameter_index'])
value = int(content['value'])
size = int(content['size'])
return backend.set_node_config_parameter(node, param, value, size)
return 'wrong input'
return 'use POST method'
"""
@api {get} /nodes/<node_id>/get_parameter/<parameter> get_parameter
@apiName get_parameter
@apiGroup Nodes
@apiParam {Number} node_id Sensor's unique ID
@apiParam {Number} parameter Parameter's unique index
@apiSuccess {String} parameter parameter's value
@apiDescription Gets the value of a given parameter of a node
"""
@app.route('/nodes/<int:node>/get_parameter/<int:param>', strict_slashes=False)
def get_config_param(node, param):
# gets a config parameter of a sensor node
return backend.get_node_config_parameter(node, param)
"""
@api {get} /nodes/<node_id>/get_battery get_battery_level
@apiName get_battery_level
@apiGroup Nodes
@apiParam {Number} node_id Sensor's unique ID
@apiSuccess {String} controller Controller name
@apiSuccess {String} location Location of the sensor
@apiSuccess {String} sensor Sensor's ID
@apiSuccess {String} type type of measurement
@apiSuccess {Number} value battery level (%)
@apiSuccess {Number} updateTime Timestamp at the measures' reception
@apiSuccessExample {json} Example of result in case of success:
{
"controller": "Pi lab1",
"location": "Room A401",
"sensor": 2,
"type": "battery",
"updateTime": 1454684168,
"value": 100
}
@apiDescription Gets the battery level of a given sensor, in a JSON format
"""
@app.route('/nodes/<int:node>/get_battery', strict_slashes=False)
def get_battery(node):
return backend.get_battery(node)
"""
@api {post} /nodes/set_location set_location
@apiName set_location
@apiGroup Nodes
@apiParam {Number} node_id Sensor's unique ID
@apiParam {String} value new location value
@apiParamExample {json} Request-Exemple :
{
'node_id' : '4',
'value' : 'A401'
}
@apiSuccess {String} location location's new value
@apiDescription Sets location of a given node
"""
@app.route('/nodes/set_location', methods=['GET','POST'], strict_slashes=False)
def set_node_location():
if request.method=='POST':
content = request.get_json()
if all(item in content.keys() for item in ['node_id','value']):
node = int(content['node_id'])
value = content['value']
return backend.set_node_location(node, value)
return 'wrong input'
return 'use POST method'
"""
@api {post} /nodes/set_name set_name
@apiName set_name
@apiGroup Nodes
@apiParam {Number} node_id Sensor's unique ID
@apiParam {String} value new name value
@apiParamExample {json} Request-Exemple :
{
'node_id' : '4',
'value' : 'A401-multisensor'
}
@apiSuccess {String} name name's new value
@apiDescription Sets name of a given node
"""
@app.route('/nodes/set_name', methods=['GET','POST'], strict_slashes=False)
def set_node_name():
if request.method=='POST':
content = request.get_json()
if all(item in content.keys() for item in ['node_id','value']):
node = int(content['node_id'])
value = content['value']
return backend.set_node_name(node, value)
return 'wrong input'
return 'use POST method'
"""
@api {get} /nodes/<node_id>/get_location get_location
@apiName get_location
@apiGroup Nodes
@apiParam {Number} node_id Sensor's unique ID
@apiSuccess {String} location location's value
@apiDescription Gets location of a given node
"""
@app.route('/nodes/<int:node>/get_location', strict_slashes=False)
def get_node_location(node):
return backend.get_node_location(node)
"""
@api {get} /nodes/<node_id>/get_name get_name
@apiName get_name
@apiGroup Nodes
@apiParam {Number} node_id Sensor's unique ID
@apiSuccess {String} name name's value
@apiDescription Gets name of a given node
"""
@app.route('/nodes/<int:node>/get_name', strict_slashes=False)
def get_node_name(node):
return backend.get_node_name(node)
"""
@api {get} /nodes/<node_id>/get_neighbours get_neighbours
@apiName get_neighbours
@apiGroup Nodes
@apiParam {Number} node_id Sensor's unique ID
@apiSuccess {String[]} neighbors list of a node's neighbours
@apiDescription Gets list of a node's neighbours
"""
@app.route('/nodes/<int:node>/get_neighbours', strict_slashes=False)
def get_neighbours_list(node):
return backend.get_neighbours_list(node)
#######################################################################################################################
############# SENSORS #################################################################################################
#######################################################################################################################
### THESE METHODS WERE SPECIALLY MADE FOR SENSOR NODES ################################################################
#######################################################################################################################
"""
@api {get} /sensors/get_sensors_list get_sensors_list
@apiName get_sensors_list
@apiGroup Sensors
@apiSuccess {String[]} JSON List of all sensor nodes in the network i a JSON format
@apiDescription Lists all sensors nodes in the network. The controller is excluded.
"""
@app.route('/sensors/get_sensors_list', strict_slashes=False)
def get_sensors_list():
# returns a list of all sensors in the network in a JSON format(only sensors)
return backend.get_sensors_list()
"""
@api {get} /sensors/<node_id>/get_all_measures get_all_measures_sensor
@apiName get_all_measures_sensor
@apiGroup Sensors
@apiParam {Number} node_id Sensor's unique ID
@apiSuccess {String} controller Controller name
@apiSuccess {String} location Location of the sensor
@apiSuccess {String} sensor Sensor's ID
@apiSuccess {Number} battery battery level (%)
@apiSuccess {Number} humidity humidity level (%)
@apiSuccess {Number} luminance luminance level (lux)
@apiSuccess {Number} temperature temperature level (C)
@apiSuccess {String} motion motion state (true or false)
@apiSuccess {Number} updateTime Timestamp at the measures' reception
@apiSuccessExample {json} Example of result in case of success:
{
"battery": 100,
"controller": "Pi lab1",
"humidity": 22,
"location": "Room A401",
"luminance": 60,
"motion": false,
"sensor": 2,
"temperature": 30.0,
"updateTime": 1454682568
}
@apiDescription Gets all measures of a given sensor, in a JSON format
"""
@app.route('/sensors/<int:node>/get_all_measures', strict_slashes=False)
def get_all_measures(node):
return backend.get_all_Measures(node)
"""
@api {get} /sensors/<node_id>/get_temperature get_temperature
@apiName get_temperature
@apiGroup Sensors
@apiParam {Number} node_id Sensor's unique ID
@apiSuccess {String} controller Controller name
@apiSuccess {String} location Location of the sensor
@apiSuccess {String} sensor Sensor's ID
@apiSuccess {String} type Type of measurement
@apiSuccess {Number} value Temperature level (C)
@apiSuccess {Number} updateTime Timestamp of the measure
@apiSuccessExample {json} Example of result in case of success:
{
"controller": "Pi lab1",
"location": "Room A401",
"sensor": 2,
"type": "temperature",
"updateTime": 1454682568,
"value": 30.4
}
@apiDescription Gets temperature of a given sensor in a JSON format
"""
@app.route('/sensors/<int:node>/get_temperature', strict_slashes=False)
def get_temperature(node):
return backend.get_temperature(node)
"""
@api {get} /sensors/<node_id>/get_humidity get_humidity
@apiName get_humidity
@apiGroup Sensors
@apiParam {Number} node_id Sensor's unique ID
@apiSuccess {String} controller Controller name
@apiSuccess {String} location Location of the sensor
@apiSuccess {String} sensor Sensor's ID
@apiSuccess {String} type type of measurement
@apiSuccess {Number} value humidity level (%)
@apiSuccess {Number} updateTime Timestamp at the measures' reception
@apiSuccessExample {json} Example of result in case of success:
{
"controller": "Pi lab1",
"location": "Room A401",
"sensor": 2,
"type": "relative humidity",
"updateTime": 1454682996,
"value": 21
}
@apiDescription Gets humidity of a given sensor in a JSON format
"""
@app.route('/sensors/<int:node>/get_humidity', strict_slashes=False)
def get_humidity(node):
return backend.get_humidity(node)
"""
@api {get} /sensors/<node_id>/get_luminance get_luminance
@apiName get_luminance
@apiGroup Sensors
@apiParam {Number} node_id Sensor's unique ID
@apiSuccess {String} controller Controller name
@apiSuccess {String} location Location of the sensor
@apiSuccess {String} sensor Sensor's ID
@apiSuccess {String} type type of measurement
@apiSuccess {Number} value luminance level (lux)
@apiSuccess {Number} updateTime Timestamp at the measures' reception
@apiSuccessExample {json} Example of result in case of success:
{
"controller": "Pi lab1",
"location": "Room A401",
"sensor": 2,
"type": "luminance",
"updateTime": 1454682996,
"value": 49
}
@apiDescription Gets humidity of a given sensor in a JSON format
"""
@app.route('/sensors/<int:node>/get_luminance', strict_slashes=False)
def get_luminance(node):
return backend.get_luminance(node)
"""
@api {get} /sensors/<node_id>/get_motion get_motion
@apiName get_motion
@apiGroup Sensors
@apiParam {Number} node_id Sensor's unique ID
@apiSuccess {String} controller Controller name
@apiSuccess {String} location Location of the sensor
@apiSuccess {String} sensor Sensor's ID
@apiSuccess {String} type type of measurement
@apiSuccess {Number} value motion state (boolean)
@apiSuccess {Number} updateTime Timestamp at the measures' reception
@apiSuccessExample {json} Example of result in case of success:
{
"controller": "Pi lab1",
"location": "Room A401",
"sensor": 2,
"type": "sensor",
"updateTime": 1454682996,
"value": true
}
@apiDescription Gets motion of a given sensor in a JSON format
"""
@app.route('/sensors/<int:node>/get_motion', strict_slashes=False)
def get_motion(node):
return backend.get_motion(node)
#############################################################################################
############## DIMMERS ################################### ##################################
#############################################################################################
### THESE METHODS WERE SPECIALLY MADE FOR DIMMER NODES ######################################
#############################################################################################
"""
@api {get} /dimmers/get_dimmers_list get_dimmers_list
@apiName get_dimmers_list
@apiGroup Actuators
@apiSuccess {String[]} JSON List of all dimmer nodes in the network i a JSON format
@apiDescription Lists all dimmer nodes in the network. The controller is excluded.
"""
@app.route('/dimmers/get_dimmers_list', strict_slashes=False)
def get_dimmers():
return backend.get_dimmers()
"""
@api {get} /dimmers/<node_id>/get_level get_dimmer_level
@apiName get_dimmer_level
@apiGroup Actuators
@apiParam {Number} node_id Dimmer's unique ID
@apiSuccess {String} controller Controller name
@apiSuccess {String} location Location of the sensor
@apiSuccess {String} dimmer Dimmer's ID
@apiSuccess {String} type type of measurement
@apiSuccess {Number} value dimmer level
@apiSuccess {Number} updateTime Timestamp at the measures' reception
@apiSuccessExample {json} Example of result in case of success:
{
"controller": "Pi lab1",
"location": "Room A401",
"dimmer": 4,
"type": "Level",
"updateTime": 1454682996,
"value": 50
}
@apiDescription Gets level of a given dimmer in a JSON format
"""
@app.route('/dimmers/<int:node_id>/get_level', strict_slashes=False)
def get_dimmer_level(node_id):
return backend.get_dimmer_level(node_id)
"""
@api {post} /dimmers/set_level get_dimmer_level
@apiName get_dimmer_level
@apiGroup Actuators
@apiParam {Number} node_id Dimmer's unique ID
@apiParam {Number} value level value ( 0<value<99 )
@apiParamExample {json} Request-Exemple :
{
'node_id' : '4',
'value' : '50'
}
@apiSuccess {String} command dimmer's new level
@apiDescription Sends command to dimmer node
"""
@app.route('/dimmers/set_level', methods=['GET', 'POST'], strict_slashes=False)
def set_dimmer_level():
if request.method=='POST':
content = request.get_json()
if all(item in content.keys() for item in ['node_id','value']):
node = int(content['node_id'])
value = int(content['value'])
if 99 < value :
value = 99
elif value < 0:
value = 0
backend.set_dimmer_level(node,value)
return "dimmer %s is set to level %s" % (node,value)
return 'wrong input'
return 'use POST method'
#################################################################
#################################################################
from logging import FileHandler, Formatter, DEBUG
if __name__ == '__main__':
try:
backend.start()
file_handler = FileHandler("flask.log")
file_handler.setLevel(DEBUG)
file_handler.setFormatter(Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
app.logger.addHandler(file_handler)
app.run(host='::', debug=False, use_reloader=False)
except KeyboardInterrupt:
backend.stop()
import requests
import json
#############################################################
#### This script sends POST or PUT http request to server ###
#############################################################
#### You have to uncomment the request you want to send ###
#############################################################
#### POST requests contain parameters in JSON format ###
#############################################################
#### Configuration of nodes
#req = requests.post('http://192.168.1.2:5000/network/set_nodes_basic_configuration',headers={'Content-Type': 'application/json'}, data=json.dumps({'Group_Interval': '240','Group_Reports':'240', 'Wake-up_Interval': '480'}))
#### Config a specific parameter
#req = requests.post('http://192.168.1.2:5000/nodes/set_parameter',headers={'Content-Type': 'application/json'}, data=json.dumps({'node_id': '4','value':'480', 'parameter_index': '111', 'size': '4'}))
#### Set node location
#req = requests.post('http://192.168.1.2:5000/nodes/set_location',headers={'Content-Type': 'application/json'}, data=json.dumps({'node_id': '4','value':'A402'}))
#### Set node name
#req = requests.post('http://192.168.1.2:5000/nodes/set_name',headers={'Content-Type': 'application/json'}, data=json.dumps({'node_id': '4','value':'sensor'}))
#### Send command to switch
#req = requests.post('http://192.168.1.2:5000/switches/send_command',headers={'Content-Type': 'application/json'}, data=json.dumps({'node_id': '3','value':'on'}))
#### Send command to dimmer
req = requests.post('http://192.168.1.2:5000/dimmers/set_level',headers={'Content-Type': 'application/json'}, data=json.dumps({'node_id': '6','value':'120'}))
#### Put controller in inclusion mode
#req = requests.put('http://192.168.1.2:5000/nodes/add_node')
#### Put controller in exclusion mode
#req = requests.put('http://192.168.1.2:5000/nodes/remove_node')
print (req.text) # print server response
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
<style>
h1{
text-align: center;
}
table{
margin-left: 3em;
margin-bottom: 3em;
border-collapse:collapse;
border: 1px solid black;
}
table tr:first-child{
background-color: yellow;
color: black;
font-size: x-large;
text-align: left;
}
table tr:first-child th:first-child{
width: 1000px;
}
table tr:first-child th:first-child{
color: black;
width: 400px;
text-align: center;
}
table tr:nth-child(n+2) td:first-child{
color: green;
font-size: large;
text-align: center;
}
table tr:nth-child(n) td:nth-child(2){
width: 1000px;
}
table tr:first-child th:nth-child(3){
width: 3000px;
}
table tr{
border: 1px solid black;
}
span{
font-family:'Courier New';
font-size:13
}
</style>
</head>
<body>
<h1>API Documentation</h1>
<p>Due to the Z-Wave specific protocol, this API Rest uses GET & POST methods for every endpoints (network, sensors, switches).</p>
<h2>Network Endpoints</h2>
<table>
<tr>
<th>Method</th>
<th>Routes</th>
<th>Description</th>
</tr>
<tr>
<td>GET</td>
<td><b><a href="/network/info">/network/info</a></b></td>
<td>Gets information about the Z-Wave network in a JSON format</td>
</tr>
<tr>
<td style="color: red;">POST</td>
<td><b>/network/set_nodes_basic_configuration</b><br/>
<td>Configure all nodes of the network with a predefined configuration. This methods configures only Group 1. All measurements (temperature, luminosity, motion and humidity) must be retrieved from the sensors after a given period of time (Group_Interval Number).</td>
</tr>
<tr>
<td>GET</td>
<td><b><a href="/network/get_nodes_configuration">/network/get_nodes_configuration</a></b><br/>
<td>Gets the list of nodes and their configuration parameters in a JSON format</td>
</tr>
<tr>
<td>GET</td>
<td><b>/network/start</b><br/>
<td>Start the Z-Wave Network</td>
</tr>
<tr>
<td>GET</td>
<td><b>/network/stop</b><br/>
<td>Stop the Z-Wave Network</td>
</tr>
<tr>
<td>GET</td>
<td><b>/network/reset</b><br/>
<td>Reset the Z-Wave Network</td>
</tr>
</table>
<h2>Nodes Endpoints (All nodes)</h2>
<table>
<tr>
<th>Method</th>
<th>Routes</th>
<th>Description</th>
</tr>
<tr>
<td>GET</td>
<td><b><a href="/nodes/get_nodes_list">/nodes/get_nodes_list</a></b></td>
<td>List all nodes in the network</td>
</tr>
<tr>
<td style="color: maroon;">PUT</td>
<td><b>/nodes/add_node</b></td>
<td>Adds Node to the network by getting the controller into inclusion mode for 20 seconds. The node can not be a controller.</td>
</tr>
<tr>
<td style="color: maroon;">PUT</td>
<td><b>/nodes/remove_node</b></td>
<td>Removes Node from the network by getting the controller into exclusion mode for 20 seconds</td>
</tr>
<tr>
<td style="color: red;">POST</td>
<td><b>/nodes/set_parameter</b></td>
<td>Sets the value of a given parameter of a node</td>
</tr>
<tr>
<td>GET</td>
<td><b>/nodes/{$node_id}/get_parameter/{$parameter_index}</b></td>
<td>Gets the value of a given parameter for node $node_id</td>
</tr>
<tr>
<td>GET</td>
<td><b>/nodes/{$node_id}/get_battery</b></td>
<td>Return current level of battery for node $node_id</td>
</tr>
<tr>
<td>GET</td>
<td><b>/nodes/{$node_id}/get_neighbours</b></td>
<td>Return the list of neighbors for node $node_id</td>
</tr>
<tr>
<td style="color: red;">POST</td>
<td><b>/nodes/set_name</b></td>
<td>Set a new name of the node</td>
</tr>
<tr>
<td style="color: red;">POST</td>
<td><b>/nodes/set_location</b></td>
<td>Set the new location of a node</td>
</tr>
<tr>
<td>GET</td>
<td><b>/nodes/{$node_id}/get_name</b></td>
<td>Get the name of the node $node_id </td>
</tr>
<tr>
<td>GET</td>
<td><b>/nodes/{$node_id}/get_location</b></td>
<td>Get the location of the node $node_id </td>
</tr>
</table>
<h2>Sensors Endpoints (Multisensors)</h2>
<table>
<tr>
<th>Method</th>
<th>Routes</th>
<th>Description</th>
</tr>
<tr>
<td>GET</td>
<td><b><a href="/sensors/get_sensors_list">/sensors/get_sensors_list</a></b></td>
<td>Display the list of all sensors in the network</td>
</tr>
<tr>
<td>GET</td>
<td><b>/sensors/{$sensor_id}/get_all_measures</b></td>
<td>Return all measures (temp, hum, lum, motion ...) for sensor $sensor_id</td>
</tr>
<tr>
<td>GET</td>
<td><b>/sensors/{$sensor_id}/get_temperature</b></td>
<td>Return current temperature for sensor $sensor_id</td>
</tr>
<tr>
<td>GET</td>
<td><b>/sensors/{$sensor_id}/get_humidity</b></td>
<td>Return current humidity for sensor $sensor_id</td>
</tr>
<tr>
<td>GET</td>
<td><b>/sensors/{$sensor_id}/get_luminance</b></td>
<td>Return current luminance for sensor $sensor_id</td>
</tr>
<tr>
<td>GET</td>
<td><b>/sensors/{$sensor_id}/get_motion</b></td>
<td>Return presence detection value for sensor $sensor_id</td>
</tr>
</table>
<h2>Actuators Endpoints </h2>
<table>
<tr>
<th>Method</th>
<th>Routes</th>
<th>Description</th>
</tr>
<tr>
<td>GET</td>
<td><b><a href="/dimmers/get_dimmers_list">/dimmers/get_dimmers_list</a></b></td>
<td>Lists all dimmer nodes in the network.</td>
</tr>
<tr>
<td>GET</td>
<td><b>/dimmers/{$dimmer_id}/get_level</a></b></td>
<td>Gets dimmer node's brightness level</td>
</tr>
<tr>
<td style="color: red;">POST</td>
<td><b>/dimmers/{$dimmer_id}/set_level</b></td>
<td>Sends command to dimmer node to set its brightness level</td>
</tr>
</table>
<br/><br/>
JSON format :<br/>
<span>{<br/>
&nbsp;&nbsp;"controller": CONTROLLER_NAME,<br/>
&nbsp;&nbsp;"location": SENSOR_LOCATION, <br/>
&nbsp;&nbsp;"sensor": SENSOR_ID,<br/>
&nbsp;&nbsp;"type": SENSOR_TYPE, <br/>
&nbsp;&nbsp;"updateTime": TIMESTAMP,<br/>
&nbsp;&nbsp;"value": SENSOR_VALUE<br/>
}<br/><br/></span>
Fields description :<br/>
<span>
&nbsp;&nbsp;<b>controller</b> : String desribing the controller (Raspberry name)<br/>
&nbsp;&nbsp;<b>location</b> : Precise location of the sensor in his network<br/>
&nbsp;&nbsp;<b>sensor</b> : Value describing the sensor (integer value)<br/>
&nbsp;&nbsp;<b>type</b> : String describing the sensor, possible values : <i>"temperature", "humidity", "presence", "luminosity"</i><br/>
&nbsp;&nbsp;<b>updateTime</b> : Timestamp of last update <br/>
&nbsp;&nbsp;<b>value</b> : Value of the sensor, possible types : <i>float</i> for temperature(deg. celsius), humidity(%age) and luminosity(lux) ; <i>boolea$
</span>
</body>
</html>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment