2013-08-30 00:29:52 +00:00
|
|
|
"""
|
|
|
|
SleekXMPP: The Sleek XMPP Library
|
|
|
|
Implementation of xeps for Internet of Things
|
|
|
|
http://wiki.xmpp.org/web/Tech_pages/IoT_systems
|
|
|
|
Copyright (C) 2013 Sustainable Innovation, Joachim.lindborg@sust.se, bjorn.westrom@consoden.se
|
|
|
|
This file is part of SleekXMPP.
|
|
|
|
|
|
|
|
See the file LICENSE for copying permission.
|
|
|
|
"""
|
|
|
|
|
|
|
|
import datetime
|
|
|
|
|
|
|
|
class Device(object):
|
2014-02-06 17:54:45 +00:00
|
|
|
"""
|
|
|
|
Example implementation of a device control object.
|
2014-08-17 22:52:24 +00:00
|
|
|
|
|
|
|
The device object may by any custom implementation to support
|
2013-08-30 00:29:52 +00:00
|
|
|
specific devices, but it must implement the functions:
|
|
|
|
has_control_field
|
|
|
|
set_control_fields
|
2014-02-06 17:54:45 +00:00
|
|
|
"""
|
2013-08-30 00:29:52 +00:00
|
|
|
|
2014-02-06 17:54:45 +00:00
|
|
|
def __init__(self, nodeId):
|
2014-08-17 22:52:24 +00:00
|
|
|
self.nodeId = nodeId
|
|
|
|
self.control_fields = {}
|
2013-08-30 00:29:52 +00:00
|
|
|
|
2014-02-06 17:54:45 +00:00
|
|
|
def has_control_field(self, field, typename):
|
|
|
|
"""
|
|
|
|
Returns true if the supplied field name exists
|
|
|
|
and the type matches for control in this device.
|
2013-08-30 00:29:52 +00:00
|
|
|
|
|
|
|
Arguments:
|
2014-08-17 22:52:24 +00:00
|
|
|
field -- The field name
|
2013-08-30 00:29:52 +00:00
|
|
|
typename -- The expected type
|
2014-02-06 17:54:45 +00:00
|
|
|
"""
|
|
|
|
if field in self.control_fields and self.control_fields[field]["type"] == typename:
|
2014-08-17 22:52:24 +00:00
|
|
|
return True
|
|
|
|
return False
|
2013-08-30 00:29:52 +00:00
|
|
|
|
2014-02-06 17:54:45 +00:00
|
|
|
def set_control_fields(self, fields, session, callback):
|
|
|
|
"""
|
|
|
|
Starts a control setting procedure. Verifies the fields,
|
|
|
|
sets the data and (if needed) and calls the callback.
|
2013-08-30 00:29:52 +00:00
|
|
|
|
|
|
|
Arguments:
|
2014-08-17 22:52:24 +00:00
|
|
|
fields -- List of control fields in tuple format:
|
2013-08-30 00:29:52 +00:00
|
|
|
(name, typename, value)
|
|
|
|
session -- Session id, only used in the callback as identifier
|
|
|
|
callback -- Callback function to call when control set is complete.
|
|
|
|
|
2014-02-06 17:54:45 +00:00
|
|
|
The callback function must support the following arguments:
|
2013-08-30 00:29:52 +00:00
|
|
|
|
2014-08-17 22:52:24 +00:00
|
|
|
session -- Session id, as supplied in the
|
2014-02-06 17:54:45 +00:00
|
|
|
request_fields call
|
|
|
|
nodeId -- Identifier for this device
|
2014-08-17 22:52:24 +00:00
|
|
|
result -- The current result status of the readout.
|
2014-02-06 17:54:45 +00:00
|
|
|
Valid values are:
|
2013-08-30 00:29:52 +00:00
|
|
|
"error" - Set fields failed.
|
|
|
|
"ok" - All fields were set.
|
2014-08-17 22:52:24 +00:00
|
|
|
error_field -- [optional] Only applies when result == "error"
|
|
|
|
The field name that failed
|
2014-02-06 17:54:45 +00:00
|
|
|
(usually means it is missing)
|
|
|
|
error_msg -- [optional] Only applies when result == "error".
|
|
|
|
Error details when a request failed.
|
|
|
|
"""
|
|
|
|
|
|
|
|
if len(fields) > 0:
|
|
|
|
# Check availiability
|
|
|
|
for name, typename, value in fields:
|
|
|
|
if not self.has_control_field(name, typename):
|
|
|
|
self._send_control_reject(session, name, "NotFound", callback)
|
2014-08-17 22:52:24 +00:00
|
|
|
return False
|
2014-02-06 17:54:45 +00:00
|
|
|
|
|
|
|
for name, typename, value in fields:
|
|
|
|
self._set_field_value(name, value)
|
|
|
|
|
2014-08-17 22:52:24 +00:00
|
|
|
callback(session, result="ok", nodeId=self.nodeId)
|
2014-02-06 17:54:45 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
def _send_control_reject(self, session, field, message, callback):
|
|
|
|
"""
|
|
|
|
Sends a reject to the caller
|
2013-08-30 00:29:52 +00:00
|
|
|
|
|
|
|
Arguments:
|
2014-08-17 22:52:24 +00:00
|
|
|
session -- Session id, see definition in
|
2013-08-30 00:29:52 +00:00
|
|
|
set_control_fields function
|
2014-08-17 22:52:24 +00:00
|
|
|
callback -- Callback function, see definition in
|
2013-08-30 00:29:52 +00:00
|
|
|
set_control_fields function
|
2014-02-06 17:54:45 +00:00
|
|
|
"""
|
2014-08-17 22:52:24 +00:00
|
|
|
callback(session, result="error", nodeId=self.nodeId, error_field=field, error_msg=message)
|
2013-08-30 00:29:52 +00:00
|
|
|
|
2014-02-06 17:54:45 +00:00
|
|
|
def _add_control_field(self, name, typename, value):
|
|
|
|
"""
|
|
|
|
Adds a control field to the device
|
2013-08-30 00:29:52 +00:00
|
|
|
|
|
|
|
Arguments:
|
|
|
|
name -- Name of the field
|
2014-08-17 22:52:24 +00:00
|
|
|
typename -- Type of the field, one of:
|
|
|
|
(boolean, color, string, date, dateTime,
|
2013-08-30 00:29:52 +00:00
|
|
|
double, duration, int, long, time)
|
|
|
|
value -- Field value
|
2014-02-06 17:54:45 +00:00
|
|
|
"""
|
2014-08-17 22:52:24 +00:00
|
|
|
self.control_fields[name] = {"type": typename, "value": value}
|
2013-08-30 00:29:52 +00:00
|
|
|
|
2014-02-06 17:54:45 +00:00
|
|
|
def _set_field_value(self, name, value):
|
|
|
|
"""
|
|
|
|
Set the value of a control field
|
2013-08-30 00:29:52 +00:00
|
|
|
|
|
|
|
Arguments:
|
|
|
|
name -- Name of the field
|
|
|
|
value -- New value for the field
|
2014-02-06 17:54:45 +00:00
|
|
|
"""
|
|
|
|
if name in self.control_fields:
|
2014-08-17 22:52:24 +00:00
|
|
|
self.control_fields[name]["value"] = value
|
2013-08-30 00:29:52 +00:00
|
|
|
|
2014-02-06 17:54:45 +00:00
|
|
|
def _get_field_value(self, name):
|
|
|
|
"""
|
|
|
|
Get the value of a control field. Only used for unit testing.
|
2013-08-30 00:29:52 +00:00
|
|
|
|
|
|
|
Arguments:
|
|
|
|
name -- Name of the field
|
2014-02-06 17:54:45 +00:00
|
|
|
"""
|
|
|
|
if name in self.control_fields:
|
2014-08-17 22:52:24 +00:00
|
|
|
return self.control_fields[name]["value"]
|
|
|
|
return None
|