class PytomationAPITests(TestCase):
    def setUp(self):
        self.api = PytomationAPI()
    
    def test_instantiation(self):
        self.assertIsNotNone(self.api)
        
    def test_device_invalid(self):
        response = self.api.get_response(method='GET', path="junk/test")
        self.assertEqual(response, 'null')
        
    def test_device_list(self):
        d=StateDevice(name='device_test_1')
        d.on()
        response = self.api.get_response(method='GET', path="devices")
        self.assertTrue('"name": "device_test_1"' in response)
    
    def test_device_get(self):
        d=StateDevice(name='device_test_1')
        d.on()
        response = self.api.get_response(method='GET', path="device/" + str(d.type_id))
        self.assertTrue('"name": "device_test_1"' in response)
        
    def test_device_on(self):
        d=StateDevice(name='device_test_1')
        d.off()
        self.assertEqual(d.state, State.OFF)
        response = self.api.get_response(method='POST', path="device/" + str(d.type_id), data=['command=on'])
        self.assertEqual(d.state, State.ON)
        self.assertTrue('"name": "device_test_1"' in response)
        
Beispiel #2
0
    def __init__(self, req, client_addr, server):
        #        self._request = req
        #        self._address = client_addr
        self._logger = PytoLogging(self.__class__.__name__)
        self._api = PytomationAPI()
        self._server = server

        SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)
Beispiel #3
0
    def __init__(self, req, client_addr, server):
        #        self._request = req
        #        self._address = client_addr
        self._logger = PytoLogging(self.__class__.__name__)
        self._api = PytomationAPI()
        self._server = server

        SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)
Beispiel #4
0
class PytomationHandlerClass(SimpleHTTPRequestHandler):
    def __init__(self, req, client_addr, server):
        #        self._request = req
        #        self._address = client_addr
        #        self._server = server
        self._logger = PytoLogging(self.__class__.__name__)
        self._api = PytomationAPI()

        SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)

    def translate_path(self, path):
        global file_path
        path = file_path + path
        return path

    def do_GET(self):
        self.route()

    def do_POST(self):
        self.route()

    def do_PUT(self):
        self.route()

    def do_DELETE(self):
        self.route()

    def do_ON(self):
        self.route()

    def do_OFF(self):
        self.route()

    def route(self):
        p = self.path.split('/')
        method = self.command
        #        print "pd:" + self.path + ":" + str(p[1:])
        if p[1].lower() == "api":
            data = None
            if method.lower() == 'post':
                length = int(self.headers.getheader('content-length'))
                data = self.rfile.read(length)
                #                print 'rrrrr' + str(length) + ":" + str(data)
                self.rfile.close()
            response = self._api.get_response(method=method,
                                              path="/".join(p[2:]),
                                              type=None,
                                              data=data)
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.send_header("Content-length", len(response))
            self.end_headers()
            self.wfile.write(response)
            self.finish()
        else:
            getattr(SimpleHTTPRequestHandler,
                    "do_" + self.command.upper())(self)
Beispiel #5
0
class PytoHandlerClass(SimpleHTTPRequestHandler):
    server = None

    def __init__(self, req, client_addr, server):
        #        self._request = req
        #        self._address = client_addr
        self._logger = PytoLogging(self.__class__.__name__)
        self._api = PytomationAPI()
        self._server = server

        SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)

    def translate_path(self, path):
        global file_path
        path = file_path + path
        return path

    def do_GET(self):
        self.route()

    def do_POST(self):
        self.route()

    def do_PUT(self):
        self.route()

    def do_DELETE(self):
        self.route()

    def do_ON(self):
        self.route()

    def do_OFF(self):
        self.route()

    def route(self):
        p = self.path.split("/")
        method = self.command
        #        print "pd:" + self.path + ":" + str(p[1:])
        if p[1].lower() == "api":
            data = None
            if method.lower() == "post":
                length = int(self.headers.getheader("content-length"))
                data = self.rfile.read(length)
                #                print 'rrrrr' + str(length) + ":" + str(data) + 'fffff' + str(self._server)
                self.rfile.close()
            response = self._api.get_response(
                method=method, path="/".join(p[2:]), type=None, data=data, source=PytoHandlerClass.server
            )
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.send_header("Content-length", len(response))
            self.end_headers()
            self.wfile.write(response)
            self.finish()
        else:
            getattr(SimpleHTTPRequestHandler, "do_" + self.command.upper())(self)
class PytomationAPITests(TestCase):
    def setUp(self):
        self.api = PytomationAPI()

    def test_instantiation(self):
        self.assertIsNotNone(self.api)

    def test_device_invalid(self):
        response = self.api.get_response(method='GET', path="junk/test")
        self.assertEqual(response, 'null')

    def test_device_list(self):
        d = StateDevice(name='device_test_1')
        d.on()
        response = self.api.get_response(method='GET', path="devices")
        self.assertTrue('"name": "device_test_1"' in response)

    def test_device_get(self):
        d = StateDevice(name='device_test_1')
        d.on()
        response = self.api.get_response(method='GET',
                                         path="device/" + str(d.type_id))
        self.assertTrue('"name": "device_test_1"' in response)

    def test_device_on(self):
        d = StateDevice(name='device_test_1')
        d.off()
        self.assertEqual(d.state, State.OFF)
        response = self.api.get_response(method='POST',
                                         path="device/" + str(d.type_id),
                                         data=['command=on'])
        self.assertEqual(d.state, State.ON)
        self.assertTrue('"name": "device_test_1"' in response)

    def test_device_level_encoded(self):
        d = Light(name='device_test_1')
        d.off()
        self.assertEqual(d.state, State.OFF)
        response = self.api.get_response(method='POST',
                                         path="device/" + str(d.type_id),
                                         data=['command=level%2C72'])
        self.assertEqual(d.state, (State.LEVEL, 72))
        self.assertTrue('"name": "device_test_1"' in response)
Beispiel #7
0
class PytoWebSocketApp(WebSocketApplication):
    _api = PytomationAPI()

    def on_open(self):
        print "WebSocket Client connected"

    def on_message(self, message):
        if message:
            self.ws.send(
                self._api.get_response(data=message, type=self._api.WEBSOCKET))

    def on_close(self, reason):
        print("WebSocket Client disconnected: ")
Beispiel #8
0
class PytoHandlerClass(SimpleHTTPRequestHandler):
    server = None

    def __init__(self, req, client_addr, server):
        #        self._request = req
        #        self._address = client_addr
        self._logger = PytoLogging(self.__class__.__name__)
        self._api = PytomationAPI()
        self._server = server

        SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)

    def translate_path(self, path):
        global file_path
        path = file_path + path
        return path

    def authenticate(self):
        auth = self.headers.get('Authorization')
        if config.auth_enabled == 'Y' and auth == None:
            self.do_AUTHHEAD()
            self.wfile.write('no auth header received'.encode())
            return None
        elif config.auth_enabled != 'Y' or auth in PytomationObject.users:
            return PytomationObject.users[auth]
        else:
            self.do_AUTHHEAD()
            self.wfile.write(self.headers.getheader('Authorization'))
            self.wfile.write('Not authenticated'.encode())
            self.wfile.write(
                ('<br />AuthConfig :' + config.auth_enabled).encode())
            return None

    def do_HEAD(self):
        print("send header")
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_AUTHHEAD(self):
        print("send header")
        self.send_response(401)
        self.send_header('WWW-Authenticate', 'Basic realm=\"Pytomation\"')
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_OPTIONS(self):
        self.send_response(200, "ok")
        self.send_header('Access-Control-Allow-Origin', '*')
        if config.auth_enabled == 'Y':
            self.send_header(
                'Access-Control-Allow-Methods',
                'GET, POST, OPTIONS, ON, OFF, DELETE, PUT, AUTHHEAD, HEAD')
            self.send_header("Access-Control-Allow-Headers", "Authorization")
        else:
            self.send_header('Access-Control-Allow-Methods',
                             'GET, POST, OPTIONS, ON, OFF, DELETE, PUT, HEAD')

    def do_GET(self):
        self.route()

    def do_POST(self):
        self.route()

    def do_PUT(self):
        self.route()

    def do_DELETE(self):
        self.route()

    def do_ON(self):
        self.route()

    def do_OFF(self):
        self.route()

    def route(self):
        user = self.authenticate()
        if not user or self.path == '/api/bridge':
            return
        p = self.path.split('/')
        method = self.command
        if p[1].lower() == "api":
            data = None
            if method.lower() == 'post':
                length = int(self.headers.get('content-length'))
                data = self.rfile.read(length)
                self.rfile.close()
            response = self._api.get_response(method=method,
                                              path="/".join(p[2:]),
                                              type=None,
                                              data=data,
                                              source=PytoHandlerClass.server,
                                              user=user)
            self.send_response(200)
            self.send_header('Access-Control-Allow-Origin', '*')
            if config.auth_enabled == 'Y':
                self.send_header(
                    'Access-Control-Allow-Methods',
                    'GET, POST, OPTIONS, ON, OFF, DELETE, PUT, AUTHHEAD, HEAD')
                self.send_header("Access-Control-Allow-Headers",
                                 "Authorization")
            else:
                self.send_header(
                    'Access-Control-Allow-Methods',
                    'GET, POST, OPTIONS, ON, OFF, DELETE, PUT, HEAD')
            self.send_header("Content-length", len(response))
            self.send_header("Content-type", "application/json")
            self.end_headers()
            self.wfile.write(response.encode())
        else:
            getattr(SimpleHTTPRequestHandler,
                    "do_" + self.command.upper())(self)
Beispiel #9
0
class PytoHandlerClass(SimpleHTTPRequestHandler):
    server = None

    def __init__(self, req, client_addr, server):
        #        self._request = req
        #        self._address = client_addr
        self._logger = PytoLogging(self.__class__.__name__)
        self._api = PytomationAPI()
        self._server = server

        SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)

    def translate_path(self, path):
        global file_path
        path = file_path + path
        return path

    def do_HEAD(self):
        print "send header"
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def do_AUTHHEAD(self):
        print "send header"
        self.send_response(401)
        self.send_header("WWW-Authenticate", 'Basic realm="Test"')
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def do_OPTIONS(self):
        self.send_response(200, "ok")
        self.send_header("Access-Control-Allow-Origin", "*")
        if config.auth_enabled == "Y":
            self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, ON, OFF, DELETE, PUT, AUTHHEAD, HEAD")
            self.send_header("Access-Control-Allow-Headers", "Authorization")
        else:
            self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, ON, OFF, DELETE, PUT, HEAD")

    def do_GET(self):
        auth_credentials = base64.b64encode(config.admin_user + ":" + config.admin_password)

        if config.auth_enabled == "Y" and self.headers.getheader("Authorization") == None:
            self.do_AUTHHEAD()
            self.wfile.write("no auth header received")
            return
        elif config.auth_enabled != "Y" or self.headers.getheader("Authorization") == "Basic " + auth_credentials:
            #            self.do_HEAD()
            #            self.wfile.write(self.headers.getheader('Authorization'))
            #            self.wfile.write('authenticated!')
            pass
        else:
            self.do_AUTHHEAD()
            self.wfile.write(self.headers.getheader("Authorization"))
            self.wfile.write("Not authenticated")
            self.wfile.write("<br />AuthConfig :" + config.auth_enabled)
            return
        self.route()

    def do_POST(self):
        self.route()

    def do_PUT(self):
        self.route()

    def do_DELETE(self):
        self.route()

    def do_ON(self):
        self.route()

    def do_OFF(self):
        self.route()

    def route(self):
        p = self.path.split("/")
        method = self.command
        #        print "pd:" + self.path + ":" + str(p[1:])
        if p[1].lower() == "api":
            data = None
            if method.lower() == "post":
                length = int(self.headers.getheader("content-length"))
                data = self.rfile.read(length)
                #                print 'rrrrr' + str(length) + ":" + str(data) + 'fffff' + str(self._server)
                self.rfile.close()
            response = self._api.get_response(
                method=method, path="/".join(p[2:]), type=None, data=data, source=PytoHandlerClass.server
            )
            self.send_response(200)
            self.send_header("Access-Control-Allow-Origin", "*")
            if config.auth_enabled == "Y":
                self.send_header(
                    "Access-Control-Allow-Methods", "GET, POST, OPTIONS, ON, OFF, DELETE, PUT, AUTHHEAD, HEAD"
                )
                self.send_header("Access-Control-Allow-Headers", "Authorization")
            else:
                self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, ON, OFF, DELETE, PUT, HEAD")
            self.send_header("Content-length", len(response))
            self.send_header("Content-type", "application/json")
            self.end_headers()
            self.wfile.write(response)
            self.finish()
        else:
            getattr(SimpleHTTPRequestHandler, "do_" + self.command.upper())(self)
Beispiel #10
0
class PytoWebSocketServer(HAInterface):
    _api = PytomationAPI()

    def __init__(self, *args, **kwargs):
        self._address = kwargs.get('address', config.http_address)
        self._port = kwargs.get('port', int(config.http_port))
        self._path = kwargs.get('path', config.http_path)
        super(PytoWebSocketServer, self).__init__(self._address, *args,
                                                  **kwargs)
        self.unrestricted = True  # To override light object restrictions

    def _init(self, *args, **kwargs):
        self._ssl_path = None
        self.ws = None
        try:
            self._ssl_path = config.ssl_path
        except:
            pass
        super(PytoWebSocketServer, self)._init(*args, **kwargs)

    def run(self):
        resource = collections.OrderedDict()
        resource['/api/bridge'] = PytoWebSocketApp
        resource['/api/device*'] = self.api_app
        resource['/api/voice'] = self.api_app
        resource['/'] = self.http_file_app
        if self._ssl_path:
            self.ws = WebSocketServer((self._address, self._port),
                                      Resource(resource),
                                      pre_start_hook=auth_hook,
                                      keyfile=self._ssl_path + '/server.key',
                                      certfile=self._ssl_path + '/server.crt')
        else:
            self.ws = WebSocketServer((self._address, self._port),
                                      Resource(resource),
                                      pre_start_hook=auth_hook)

        print "Serving WebSocket Connection on", self._address, "port", self._port, "..."
        StateDevice.onStateChangedGlobal(self.broadcast_state)
        self.ws.serve_forever()

    def api_app(self, environ, start_response):
        method = environ['REQUEST_METHOD'].lower()
        if method == 'post':
            data = environ['wsgi.input'].read()
        else:
            data = None
        start_response("200 OK", [("Content-Type", "text/html"),
                                  ('Access-Control-Allow-Origin', '*')])
        return self._api.get_response(path='/'.join(
            environ['PATH_INFO'].split('/')[2:]),
                                      source=PytoWebSocketServer,
                                      method=method,
                                      data=data)

    def http_file_app(self, environ, start_response):
        path_info = environ['PATH_INFO']
        http_file = self._path + path_info
        if self._ssl_path:
            protocol = 'https://'
        else:
            protocol = 'http://'

        if os.path.exists(http_file):
            if os.path.isdir(http_file):
                if http_file.endswith('/'):
                    http_file += 'index.html'
                else:
                    if path_info.startswith('/'):
                        location = protocol + self._address + ':' + str(
                            self._port) + path_info + '/'
                    else:
                        location = protocol + self._address + ':' + str(
                            self._port) + '/' + path_info + '/'
                    start_response("302 Found",
                                   [("Location", location),
                                    ('Access-Control-Allow-Origin', '*')])
                    return ''

            mime = mimetypes.guess_type(http_file)
            start_response("200 OK", [("Content-Type", mime[0]),
                                      ('Access-Control-Allow-Origin', '*')])
            return open(http_file, "rb")
        else:
            start_response("404 Not Found",
                           [("Content-Type", "text/html"),
                            ('Access-Control-Allow-Origin', '*')])
            return "404 Not Found"

    def broadcast_state(self, state, source, prev, device):
        # TODO: add queue system and separate thread to avoid blocking on long network operations
        if self.ws:
            for client in self.ws.clients.values():
                message = self._api.get_state_changed_message(
                    state, source, prev, device)
                client.ws.send(message)
Beispiel #11
0
class PytoHandlerClass(SimpleHTTPRequestHandler):
    server = None

    def __init__(self, req, client_addr, server):
        #        self._request = req
        #        self._address = client_addr
        self._logger = PytoLogging(self.__class__.__name__)
        self._api = PytomationAPI()
        self._server = server

        SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)

    def translate_path(self, path):
        global file_path
        path = file_path + path
        return path

    def do_HEAD(self):
        print "send header"
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_AUTHHEAD(self):
        print "send header"
        self.send_response(401)
        self.send_header('WWW-Authenticate', 'Basic realm=\"Test\"')
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_GET(self):
        auth_credentials = base64.b64encode(config.admin_user + ":" +
                                            config.admin_password)

        if self.headers.getheader('Authorization') == None:
            self.do_AUTHHEAD()
            self.wfile.write('no auth header received')
            return
        elif self.headers.getheader(
                'Authorization') == 'Basic ' + auth_credentials:
            #            self.do_HEAD()
            #            self.wfile.write(self.headers.getheader('Authorization'))
            #            self.wfile.write('authenticated!')
            pass
        else:
            self.do_AUTHHEAD()
            self.wfile.write(self.headers.getheader('Authorization'))
            self.wfile.write('Not authenticated')
            return
        self.route()

    def do_POST(self):
        self.route()

    def do_PUT(self):
        self.route()

    def do_DELETE(self):
        self.route()

    def do_ON(self):
        self.route()

    def do_OFF(self):
        self.route()

    def route(self):
        p = self.path.split('/')
        method = self.command
        #        print "pd:" + self.path + ":" + str(p[1:])
        if p[1].lower() == "api":
            data = None
            if method.lower() == 'post':
                length = int(self.headers.getheader('content-length'))
                data = self.rfile.read(length)
                #                print 'rrrrr' + str(length) + ":" + str(data) + 'fffff' + str(self._server)
                self.rfile.close()
            response = self._api.get_response(method=method,
                                              path="/".join(p[2:]),
                                              type=None,
                                              data=data,
                                              source=PytoHandlerClass.server)
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.send_header("Content-length", len(response))
            self.end_headers()
            self.wfile.write(response)
            self.finish()
        else:
            getattr(SimpleHTTPRequestHandler,
                    "do_" + self.command.upper())(self)
Beispiel #12
0
class PytoHandlerClass(SimpleHTTPRequestHandler):
    server = None

    def __init__(self,req, client_addr, server):
#        self._request = req
#        self._address = client_addr
        self._logger = PytoLogging(self.__class__.__name__)
        self._api = PytomationAPI()
        self._server = server

        SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)

    def translate_path(self, path):
        global file_path
        path = file_path + path
        return path

    def do_HEAD(self):
        print "send header"
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_AUTHHEAD(self):
        print "send header"
        self.send_response(401)
        self.send_header('WWW-Authenticate', 'Basic realm=\"Test\"')
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_GET(self):
        auth_credentials = base64.b64encode(config.admin_user + ":" + config.admin_password)
        
        if config.auth_enabled == 'Y' and self.headers.getheader('Authorization') == None:
            self.do_AUTHHEAD()
            self.wfile.write('no auth header received')
            return
        elif config.auth_enabled != 'Y' or self.headers.getheader('Authorization') == 'Basic ' + auth_credentials:
#            self.do_HEAD()
#            self.wfile.write(self.headers.getheader('Authorization'))
#            self.wfile.write('authenticated!')
            pass
        else:
            self.do_AUTHHEAD()
            self.wfile.write(self.headers.getheader('Authorization'))
            self.wfile.write('Not authenticated')
            self.wfile.write('<br />AuthConfig :' + config.auth_enabled)
            return
        self.route()

    def do_POST(self):
        self.route()

    def do_PUT(self):
        self.route()
        
    def do_DELETE(self):
        self.route()

    def do_ON(self):
        self.route()
        
    def do_OFF(self):
        self.route()

    def route(self):
        p = self.path.split('/')
        method = self.command
#        print "pd:" + self.path + ":" + str(p[1:])
        if p[1].lower() == "api":
            data = None
            if method.lower() == 'post':
                length = int(self.headers.getheader('content-length'))
                data = self.rfile.read(length)
#                print 'rrrrr' + str(length) + ":" + str(data) + 'fffff' + str(self._server)
                self.rfile.close()
            response = self._api.get_response(method=method, path="/".join(p[2:]), type=None, data=data, source=PytoHandlerClass.server)
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.send_header("Content-length", len(response))
            self.end_headers()
            self.wfile.write(response)
            self.finish()
        else:
            getattr(SimpleHTTPRequestHandler, "do_" + self.command.upper())(self)
Beispiel #13
0
 def setUp(self):
     self.api = PytomationAPI()
Beispiel #14
0
 def setUp(self):
     self.api = PytomationAPI()