def request_devices(self, device_type): """List the devices""" devices_url = "https://graph.api.smartthings.com%s/%s" % ( self.endpointd["url"], device_type, ) devices_paramd = {} devices_headerd = { "Authorization": "Bearer %s" % self.std["access_token"], } devices_response = requests.get(url=devices_url, params=devices_paramd, headers=devices_headerd) self.deviceds = devices_response.json() for switchd in self.deviceds: switchd['url'] = "%s/%s" % ( devices_url, switchd['id'], ) if self.verbose: iotdb_log.log( "devices", url=devices_url, paramd=devices_paramd, deviceds=self.deviceds, ) return self.deviceds
def request_devices(self, device_type): """List the devices""" devices_url = "https://%s%s/%s" % ( self.std.get("api_location", "graph.api.smartthings.com"), self.endpointd["url"], device_type, ) devices_paramd = { } devices_headerd = { "Authorization": "Bearer %s" % self.std["access_token"], } devices_response = requests.get(url=devices_url, params=devices_paramd, headers=devices_headerd) try: self.deviceds = devices_response.json() except ValueError: SmartThings.raise_request_errors(devices_response) raise Exception("Received invalid JSON response") SmartThings.raise_api_errors(self.deviceds) for switchd in self.deviceds: switchd['url'] = "%s/%s" % ( devices_url, switchd['id'], ) if self.verbose: iotdb_log.log( "devices", url=devices_url, paramd=devices_paramd, deviceds=self.deviceds, ) return self.deviceds
def request_endpoints(self): """Get the endpoints exposed by the SmartThings App The first command you need to call """ endpoints_url = self.std["api"] endpoints_paramd = {"access_token": self.std["access_token"]} endpoints_response = requests.get(url=endpoints_url, params=endpoints_paramd) try: endpoints = endpoints_response.json() except ValueError: SmartThings.raise_request_errors(endpoints_response) raise Exception("Received invalid JSON response") SmartThings.raise_api_errors(endpoints) self.endpointd = endpoints[0] if self.verbose: iotdb_log.log( "endpoints", endpoints_url=endpoints_url, endpoints_paramd=endpoints_paramd, resultds=self.endpointd, )
def request_endpoints(self): """Get the endpoints exposed by the SmartThings App The first command you need to call """ endpoints_url = self.std["api"] endpoints_paramd = { "access_token": self.std["access_token"] } endpoints_response = requests.get(url=endpoints_url, params=endpoints_paramd) try: endpoints = endpoints_response.json() except ValueError: SmartThings.raise_request_errors(endpoints_response) raise Exception("Received invalid JSON response") SmartThings.raise_api_errors(endpoints) self.endpointd = endpoints[0] if self.verbose: iotdb_log.log( "endpoints", endpoints_url=endpoints_url, endpoints_paramd=endpoints_paramd, resultds=self.endpointd, )
def on_service_register(self, sdRef, flags, errorCode, name, regtype, domain): import pybonjour if errorCode == pybonjour.kDNSServiceErr_NoError: bonjour="%s.%s%s" % ( name, regtype, domain, ) iotdb_log.log("BonjourServer: registered service", name=name, regtype=regtype, domain=domain, bonjour=bonjour, ) if self.save: served(self.name, { "bonjour":bonjour }, update=True)
def run(self, handler): # pragma: no cover from wsgiref.simple_server import make_server, WSGIRequestHandler if self.quiet: class QuietHandler(WSGIRequestHandler): def log_request(*args, **kw): pass self.options['handler_class'] = QuietHandler srv = make_server(self.host, self.port, handler, **self.options) iotdb_log.log("PortServer: ACTUALLY listening", on = "http://%s:%s/" % ( self.host, self.port, )) if self.save: served(self.name, { "url" : "http://%s:%s/" % ( self.host, self.port, ), }) srv.serve_forever()
def diffd(od, nd, dpath): for key in set(od.keys() + nd.keys()): ovalue = od.get(key) nvalue = nd.get(key) ## iotdb_log.log(ndpath=dpath + [ key ], ovalue=ovalue, nvalue=nvalue) if ovalue == nvalue: continue ndpath = dpath + [ key ] if isinstance(ovalue, dict) and isinstance(nvalue, dict): for r in diffd(ovalue, nvalue, ndpath): yield r else: iotdb_log.log("change", dpath=ndpath, ovalue=ovalue, nvalue=nvalue) yield ndpath, nvalue
def on_update(thing, url_path, old_stated, new_stated): if old_stated == new_stated: return iotdb_log.log("on_update", name=thing.name, url_path=url_path, old_stated=old_stated, new_stated=new_stated) if not options.mqtt_host: return url_path = url_path.split("/") mqtt_topic = options.mqtt_topic.split("/") def diffd(od, nd, dpath): for key in set(od.keys() + nd.keys()): ovalue = od.get(key) nvalue = nd.get(key) ## iotdb_log.log(ndpath=dpath + [ key ], ovalue=ovalue, nvalue=nvalue) if ovalue == nvalue: continue ndpath = dpath + [ key ] if isinstance(ovalue, dict) and isinstance(nvalue, dict): for r in diffd(ovalue, nvalue, ndpath): yield r else: iotdb_log.log("change", dpath=ndpath, ovalue=ovalue, nvalue=nvalue) yield ndpath, nvalue mqttc = None for ndpath, nvalue in diffd(old_stated, new_stated, []): path = mqtt_topic + url_path + ndpath path = filter(None, path) topic = "/".join(path) message = json.dumps(nvalue) if not mqttc: mqttc = mosquitto.Mosquitto() mqttc.connect(options.mqtt_host, int(options.mqtt_port), 60) mqttc.publish(topic, message, 1) iotdb_log.log("MQTT.publish", topic=topic, msg=message, mqtt_host=options.mqtt_host, mqtt_port=options.mqtt_port, )
def request_endpoints(self): """Get the endpoints exposed by the SmartThings App The first command you need to call """ endpoints_url = self.std["api"] endpoints_paramd = { "access_token": self.std["access_token"] } endpoints_response = requests.get(url=endpoints_url, params=endpoints_paramd) self.endpointd = endpoints_response.json()[0] if self.verbose: iotdb_log.log( "endpoints", endpoints_url=endpoints_url, endpoints_paramd=endpoints_paramd, resultds=self.endpointd, )
def run(self, handler): # pragma: no cover from wsgiref.simple_server import make_server, WSGIRequestHandler if self.quiet: class QuietHandler(WSGIRequestHandler): def log_request(*args, **kw): pass self.options['handler_class'] = QuietHandler srv = make_server("0.0.0.0", 0, handler, **self.options) port = srv.socket.getsockname()[1] iotdb_log.log("BonjourServer: ACTUALLY listening", on = "http://0.0.0.0:%s/" % ( port, )) if self.save: served(self.name, { "url" : "http://0.0.0.0:%s/" % ( port, ), }) self.register_bonjour( port=port, name=self.name, regtype=self.regtype, ) srv.serve_forever()
def request_devices(self, device_type): """List the devices""" devices_url = "https://%s%s/%s" % ( self.std.get("api_location", "graph.api.smartthings.com"), self.endpointd["url"], device_type, ) devices_paramd = {} devices_headerd = { "Authorization": "Bearer %s" % self.std["access_token"], } devices_response = requests.get(url=devices_url, params=devices_paramd, headers=devices_headerd) try: self.deviceds = devices_response.json() except ValueError: SmartThings.raise_request_errors(devices_response) raise Exception("Received invalid JSON response") SmartThings.raise_api_errors(self.deviceds) for switchd in self.deviceds: switchd['url'] = "%s/%s" % ( devices_url, switchd['id'], ) if self.verbose: iotdb_log.log( "devices", url=devices_url, paramd=devices_paramd, deviceds=self.deviceds, ) return self.deviceds
def request_devices(self, device_type): """List the devices""" devices_url = "https://graph.api.smartthings.com%s/%s" % ( self.endpointd["url"], device_type, ) devices_paramd = { } devices_headerd = { "Authorization": "Bearer %s" % self.std["access_token"], } devices_response = requests.get(url=devices_url, params=devices_paramd, headers=devices_headerd) self.deviceds = devices_response.json() for switchd in self.deviceds: switchd['url'] = "%s/%s" % ( devices_url, switchd['id'], ) if self.verbose: iotdb_log.log( "devices", url=devices_url, paramd=devices_paramd, deviceds=self.deviceds, ) return self.deviceds
def put(path = ""): subthing = self._subthing(path) if not subthing: bottle.response.content_type = "text/plain" return "Not found\n" if not bottle.request.json: iotdb_log.log("soft error - no JSON request") else: if self.on_update: old_stated = self._serialize_out(subthing.stated) subthing._update(bottle.request.json) if 0: iotdb_log.log(name=self.name, new_stated=self._serialize_out(subthing.stated), request=bottle.request.json, ) if self.on_update: new_stated = self._serialize_out(subthing.stated) self.on_update(self, path, old_stated, new_stated) return self.render(self, subthing.stated)
def cli(): dtypes = [ "switch", "motion", "presence", "acceleration", "contact", "temperature", "battery", "acceleration", "threeAxis", ] parser = OptionParser() parser.add_option( "", "--debug", default = False, action = "store_true", dest = "debug", help = "", ) parser.add_option( "", "--verbose", default = False, action = "store_true", dest = "verbose", help = "", ) parser.add_option( "", "--type", dest = "device_type", help = "The device type (required), one of %s" % ", ".join(dtypes) ) parser.add_option( "", "--id", dest = "device_id", help = "The ID or Name of the device to manipulate" ) parser.add_option( "", "--request", dest = "request", help = "Something to do, e.g. 'switch=1', 'switch=0'" ) parser.add_option( "", "--rest", dest = "rest_request", help = "Issue a rest request to the smartthings app" ) parser.add_option( "", "--rest_param", dest = "rest_param", help = "holds rest call parameters" ) (options, args) = parser.parse_args() if not options.rest_request and not options.device_type: print >> sys.stderr, "%s: --type <%s>" % ( sys.argv[0], "|".join(dtypes)) parser.print_help(sys.stderr) sys.exit(1) st = SmartThings(verbose=options.verbose) st.load_settings() st.request_endpoints() if options.rest_request: pprint.pprint( st.rest_request(options.rest_request, options.rest_param)) else: ds = st.request_devices(options.device_type) if options.device_id: ds = filter(lambda d: options.device_id in [ d.get("id"), d.get("label"), ], ds) if options.request: key, value = options.request.split('=', 2) try: value = int(value) except ValueError: pass requestd = { key: value } for d in ds: iotdb_log.log(device=d, request=requestd) st.device_request(d, requestd) else: print json.dumps(ds, indent=2, sort_keys=True)
parser.print_help(sys.stderr) sys.exit(1) st = SmartThings(verbose=options.verbose) st.load_settings() st.request_endpoints() ds = st.request_devices(options.device_type) if options.device_id: ds = filter(lambda d: options.device_id in [ d.get("id"), d.get("label"), ], ds) if options.request: key, value = options.request.split('=', 2) try: value = int(value) except ValueError: pass requestd = { key: value } for d in ds: iotdb_log.log(device=d, request=requestd) st.device_request(d, requestd) else: print json.dumps(ds, indent=2, sort_keys=True)
def cli(): dtypes = [ "switch", "motion", "presence", "acceleration", "contact", "temperature", "battery", "acceleration", "threeAxis", ] parser = OptionParser() parser.add_option( "", "--debug", default=False, action="store_true", dest="debug", help="", ) parser.add_option( "", "--verbose", default=False, action="store_true", dest="verbose", help="", ) parser.add_option("", "--type", dest="device_type", help="The device type (required), one of %s" % ", ".join(dtypes)) parser.add_option("", "--id", dest="device_id", help="The ID or Name of the device to manipulate") parser.add_option("", "--request", dest="request", help="Something to do, e.g. 'switch=1', 'switch=0'") parser.add_option("", "--rest", dest="rest_request", help="Issue a rest request to the smartthings app") parser.add_option("", "--rest_param", dest="rest_param", help="holds rest call parameters") (options, args) = parser.parse_args() if not options.rest_request and not options.device_type: print >> sys.stderr, "%s: --type <%s>" % (sys.argv[0], "|".join(dtypes)) parser.print_help(sys.stderr) sys.exit(1) st = SmartThings(verbose=options.verbose) st.load_settings() st.request_endpoints() if options.rest_request: pprint.pprint(st.rest_request(options.rest_request, options.rest_param)) else: ds = st.request_devices(options.device_type) if options.device_id: ds = filter( lambda d: options.device_id in [ d.get("id"), d.get("label"), ], ds) if options.request: key, value = options.request.split('=', 2) try: value = int(value) except ValueError: pass requestd = {key: value} for d in ds: iotdb_log.log(device=d, request=requestd) st.device_request(d, requestd) else: print json.dumps(ds, indent=2, sort_keys=True)
def _update(self, updated, stated = None): if stated == None: stated = self.stated for key, new_value in updated.iteritems(): if isinstance(new_value, list): iotdb_log.log("cannot deal with a 'list' value -- ignoring", key=key, value=new_value) continue elif isinstance(new_value, dict): subthing = stated.get(key) if isinstance(subthing, dict): for subkey, sub_old_value in subthing.iteritems(): sub_new_value = new_value.get(subkey) if sub_new_value == None: continue if isinstance(sub_old_value, Thing): sub_old_value._update(sub_new_value) else: iotdb_log.log("don't know what to do here yet", subkey=subkey, sub_new_value=sub_new_value, sub_old_value=sub_old_value) ; ## self._update(updated, subvalue) elif isinstance(subthing, Thing): subthing._update(new_value) else: iotdb_log.log("nested state was not a Thing -- ignoring", key=key, value=new_value, subthing=subthing) continue elif new_value == None: iotdb_log.log("cannot deal with None -- ignoring", key=key, value=new_value) continue else: old_value = stated.get(key) if old_value == None: iotdb_log.log("key not found -- ignoring", key=key, value=new_value, stated=stated) continue try: new_value = old_value.__class__(new_value) assert(new_value.__class__ == old_value.__class__) except: iotdb_log.log("new_value could not be coerced to type of old_value", exception = True, old_value = old_value, new_value = new_value) continue validatet = self.validated.get(key) if validatet: validate_f = validatet[0] validate_args = validatet[1:] new_value = validate_f(new_value, old_value, *validate_args) if new_value == old_value: continue stated[key] = new_value self.validate();
raise if __name__ == '__main__': try: if not args: raise OptionException, "<module> required after arguments" SERVE_MODULE = args[0] except SystemExit: raise except OptionException, s: print >> sys.stderr, "%s: %s\n" % ( sys.argv[0], s, ) parser.print_help(sys.stderr) sys.exit(1) except Exception, x: iotdb_log.log(exception = True) parser.print_help(sys.stderr) sys.exit(1) if options.pidfile: with open(options.pidfile, 'w') as fout: fout.write("%d\n" % os.getpid()) if options.mqtt_host: import mosquitto def render_json(thing, d): bottle.response.content_type = MIME_JSON bottle.response.add_header("Access-Control-Allow-Origin", "*") bottle.response.add_header("Access-Control-Allow-Methods", "GET, PUT, POST")