def run(): global initialized, connected while True: # init slack init() if not initialized: time.sleep(sleep_on_error) continue # connect to slack connect() if not connected: time.sleep(sleep_on_error) continue # read a rtm stream try: output_list = slack.rtm_read() except Exception,e: log.warning("unable to read from slack: "+utils.get_exception(e)) initialized = False connected = False time.sleep(sleep_on_error) continue if output_list and len(output_list) > 0: for output in output_list: if not output or 'text' not in output: continue if output['user'] == bot_id: continue # for each output if bot_id in output['text'] or bot_name in output['text'] or output['channel'].startswith("D"): # if the message is to the bot request = output['text'] request = request.replace(bot_name,'') request = request.replace(bot_id,'') request = request.lower() channel = output['channel'] # ask the oracle what to respond response = oracle.ask(request) if response["type"] == "text": # post the text response slack_message(channel,response["content"]) elif response["type"] == "chart": # post a waiting message slack_message(channel,oracle.get_wait_message()) # generate the image module_id,widget_id = response["content"].split(",") try: files = generate_widget.run(module_id,widget_id) except Exception,e: log.warning("unable to generate the widget for "+module_id+":"+widget_id+": "+utils.get_exception(e)) continue # upload the chart to the channel if len(files) > 0: filename = utils.get_widget_file(files[0]) log.debug("uploading "+filename) widget = utils.get_widget(module_id,widget_id) slack_upload(channel,filename,utils.lang(widget["display_name"])) else: slack_message(channel,"unable to find the chart "+filename)
def tx(self, node_id, child_id, command_string, type_string, payload, ack=0, service_message=False): # map the correspoding command and type command = commands.index(command_string) type = types[command].index(type_string) ack_string = acks[ack] if not service_message: log.info("[" + self.gateway_id + "][" + str(node_id) + "][" + str(child_id) + "][" + command_string + "][" + type_string + "] sending message: " + str(payload)) # send the message to the gateway if self.gateway_type == "serial": # prepare the message msg = str(node_id) + ";" + str(child_id) + ";" + str( command) + ";" + str(ack) + ";" + str(type) + ";" + str( payload) + "\n" # send the message through the serial port try: self.gateway.write(msg) except Exception, e: log.error("[" + self.gateway_id + "] unable to send " + str(msg) + " to the serial gateway: " + utils.get_exception(e))
def data_send(module_id, group_id, sensor_id, value, force=False): sensor = utils.get_sensor(module_id, group_id, sensor_id) if sensor is None: log.error("[" + module_id + "][" + group_id + "][" + sensor_id + "] sensor not found") return json.dumps("KO") log.debug("[" + module_id + "][" + group_id + "][" + sensor_id + "] sending message: " + str(value)) sensor = init_sensor(sensor) if not hasattr(plugins[sensor["plugin"]["plugin_name"]], 'send'): log.error("the plugin " + sensor["plugin"]["plugin_name"] + " does not allow sending messages") return json.dumps("KO") try: try: # invoke the plugin-specific send function plugins[sensor["plugin"]["plugin_name"]].send(sensor, value, force=force) except TypeError: # not all the plugins support "force", call it without it plugins[sensor["plugin"]["plugin_name"]].send(sensor, value) return json.dumps("OK") except Exception, e: log.error("unable to send " + str(value) + ": " + utils.get_exception(e))
def init(): global slack global bot_id global channel_id global initialized if initialized: return log.info("Initializing slack...") # initialize the library try: # initialize the library slack = SlackClient(conf["output"]["slack"]["bot_token"]) # test the authentication auth = slack.api_call("auth.test") if not auth["ok"]: log.error("authentication failed: "+auth["error"]) return # retrieve the bot id global bot_id bot_id = get_user_id(bot_name) if bot_id is None: log.error("unable to find your bot "+bot_name+". Ensure it is configured correctly") return # retrieve the channel id global channel_id channel_id = get_channel_id(channel_name) if channel_id is None: log.error("unable to find the channel "+channel_name) return initialized = True except Exception,e: log.warning("unable to initialize slack: "+utils.get_exception(e))
def test_negative_auth_post_saml_invalid_saml(self): """ Check exception raised while posting saml with invalid saml, and verify the exception contains correct error messages. """ # get auth first head, content = utils.auth_get_auth() # get cookie cookie = head['set-cookie'] logging.info("The retrieved cookie from Auth server is '%s'" % str(cookie)) header = utils.headers header['cookie'] = cookie logging.debug("The requested headers are '%s'" % str(header)) http = httplib2.Http() # construct invalid responses invalid_saml = [utils.random_str()] for isa in invalid_saml: logging.info("The invalid saml to be tested is '%s'" % str(isa)) url = 'http://' + utils.auth_server + '/' + utils.auth_partner + '/saml' logging.info("The requested url is '%s'" % url) saml = {'SAMLResponse': isa} h, c = http.request(url, 'POST', headers = header, body = urlencode(saml)) # assert response head status is 400 self.assertEqual(int(h['status']), 400) # assert error msg is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception("InvalidSAML", "AuthPostSamlGrantExceptions"), self)
def poll(sensor): # authenticate against icloud try: icloud = PyiCloudService(sensor["plugin"]["username"]) except Exception, e: log.warning("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "] unable to access icloud: " + utils.get_exception(e)) return ""
def parse(self, message): log.debug("[" + self.gateway_id + "] received " + str(message)) # parse the message try: node_id, child_id, command, ack, type, payload = message.split(";") except Exception, e: log.warning("[" + self.gateway_id + "] Invalid format (" + message + "): " + utils.get_exception(e)) return None
def notify(text): # connect to the modem try: log.debug("Connecting to GSM modem on port " + settings["port"] + " with baud rate " + str(settings["baud"])) modem = serial.Serial(settings["port"], settings["baud"], timeout=0.5) except Exception, e: log.error("Unable to connect to the GSM modem: " + utils.get_exception(e)) return
def run(): # connect to the gateway try: log.info("Connecting to MQTT gateway on " + plugin_conf["hostname"] + ":" + str(plugin_conf["port"])) client = mqtt.Client() client.connect(plugin_conf["hostname"], plugin_conf["port"], 60) except Exception, e: log.warning("Unable to connect to the MQTT gateway: " + utils.get_exception(e)) return
def test_negative_get_auth_horizon_partner_not_exist(self): """ Check exception raised while getting auth for not existent partner, and verify the exception contains correct error messages. """ nosub = utils.random_str() logging.info("The not existent subdomain to be tested is '%s'" % nosub) with self.assertRaises(rest.RequestFailed) as e: self.res.get('/auth/config/' + (nosub), headers=utils.headers) self.assertEqual(self.res.response.status, 400) # verify the exception is expected utils.verify_rest_requetfailed_exception(e,utils.get_exception('UnknownSubdomain', 'GetAuthExceptions'), self)
def mqtt_on_message(client, userdata, msg): try: log.debug("[" + self.gateway_id + "] received " + str(msg.topic) + ": " + str(payload)) # split the topic topic, node_id, child_id, command, ack, type = msg.topic.split( "/") except Exception, e: log.error("[" + self.gateway_id + "] Invalid format (" + msg.topic + "): " + utils.get_exception(e)) return False
def send(to, text): protocol = "https://" if settings["ssl"] else "http://" url = protocol + settings[ "hostname"] + "/myaccount/sendsms.php?username="******"username"] + "&password="******"password"] + "&from=" + str( settings["from"]) + "&to=" + str(to) + "&text=" + text try: response = utils.web_get(url, timeout=timeout) except Exception, e: log.warning("unable to connect to the sms service: " + utils.get_exception(e)) return False
def parse(sensor): # retrieve the raw data from the cache data = db.range(sensor["db_cache"], withscores=False) if len(data) == 0: log.warning("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "]: no data to parse") return None data = data[0] measures = None try: # parse the cached data measures = plugins[sensor['plugin']['plugin_name']].parse(sensor, data) if not isinstance(measures, list): # returned a single value, build the data structure value = measures measures = [] measure = {} measure["key"] = sensor["sensor_id"] measure["value"] = value measures.append(measure) # format each value for i in range(len(measures)): # post-process the measure if configured if "command_transform" in sensor: orig_value = measures[i]["value"] command = sensor["command_transform"].replace( "%value%", str(orig_value)) measures[i]["value"] = utils.run_command(command) log.debug("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "] transforming " + str(orig_value) + " into " + str(measures[i]["value"])) # normalize the measures if sensor["format"] == "temperature": measures[i]["value"] = utils.temperature_unit( measures[i]["value"]) if sensor["format"] == "length": measures[i]["value"] = utils.length_unit(measures[i]["value"]) if sensor["format"] == "pressure": measures[i]["value"] = utils.pressure_unit( measures[i]["value"]) if sensor["format"] == "speed": measures[i]["value"] = utils.speed_unit(measures[i]["value"]) measures[i]["value"] = utils.normalize( measures[i]["value"], conf["constants"]["formats"][sensor["format"]]["formatter"]) log.debug("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "] parsed: " + str(measures)) except Exception, e: log.warning("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "] unable to parse " + str(data) + ": " + utils.get_exception(e)) return None
def test_negative_get_tokens_invalid_token(self): """ Check exception raised while getting tokens information with invalid tokens, and verify the exception contains correct error messages. """ malpayloads = [utils.random_str()] for mp in malpayloads: logging.info("The malpayload acting unauthorized client is '%s'" % mp) with self.assertRaises(Exception) as e: self.res.get('/tokens/'+mp, headers=utils.headers) self.assertEqual(self.res.response.status, 404) # verify the retrieved exception is expected utils.verify_rest_requetfailed_exception(e, utils.get_exception('InvalidToken', 'GetTokensExceptions'), self)
def read(self): line = "" if self.gateway_type == "serial": # read a line try: line = self.gateway.readline().rstrip() except Exception, e: log.error( "[" + self.gateway_id + "] Unable to receive data from the serial gateway: " + utils.get_exception(e)) return None
def test_negative_delete_tokens_parameter_missing(self): """ Check exception raised while deleting tokens without giving parameter, and verify the exception contains correct error messages. """ malpayloads = [''] for mp in malpayloads: logging.info("The malpayload acting unauthorized client is '%s'" % mp) with self.assertRaises(rest.RequestFailed) as e: self.res.delete('/tokens/'+mp, headers=utils.headers) self.assertEqual(self.res.response.status, 400) # verify the retrieved exception is expected utils.verify_rest_requetfailed_exception(e, utils.get_exception('ParameterMissing', 'DeleteTokensExceptions'), self)
def notify(text): text = "[" + conf["general"]["house_name"] + "] " + text # truncate the text text = (data[:150] + '..') if len(text) > 150 else text # connect to the modem try: log.debug("Connecting to GSM modem on port " + settings["port"] + " with baud rate " + str(settings["baud"])) modem = serial.Serial(settings["port"], settings["baud"], timeout=0.5) except Exception, e: log.error("Unable to connect to the GSM modem: " + utils.get_exception(e)) return
def test_negative_auth_get_auth_missing_URI(self): """ Check exception raised while getting auth for missing uri, and verify the exception contains correct error messages. """ http = httplib2.Http() # construct invalid client id url = 'http://' + utils.auth_server + '/' + utils.auth_partner + '/authorize?' + 'response_type=token' + '&client_id=' + utils.auth_client_id_no_uri logging.info("The requested url is '%s'" % url) h,c = http.request(url, 'GET', headers = utils.headers) logging.debug("The retrieved header is '%s'" % str(h)) logging.debug("The retrieved content is '%s'" % str(c)) # assert it's a bad request self.assertEqual(int(h['status']), 400) # assert the exception content is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception('MissingURI', 'AuthGetAuthExceptions'), self)
def connect(self): if self.gateway_type == "serial": try: # connect to the serial gateway log.info("[" + self.gateway_id + "] Connecting to serial gateway on " + self.gateway_conf["port"] + " with baud rate " + str(self.gateway_conf["baud"])) self.gateway = serial.Serial(self.gateway_conf["port"], self.gateway_conf["baud"]) except Exception, e: log.error("[" + self.gateway_id + "] Unable to connect to the serial gateway: " + utils.get_exception(e)) return False
def test_negative_auth_get_auth_invalid_response_type(self): """ Check exception raised while getting auth for invalid respone type other than 'token', and verify the exception contains correct error messages. """ http = httplib2.Http() # construct invalid responses invalid_response = ['', utils.random_str()] for ir in invalid_response: logging.info("The invalid response type to be tested is '%s'" % str(ir)) url = 'http://' + utils.auth_server + '/' + utils.auth_partner + '/authorize?' + 'response_type=' + ir + '&client_id=' + utils.auth_client_id logging.info("The requested url is '%s'" % url) h,c = http.request(url, 'GET', headers = utils.headers) # assert it's a bad request self.assertEqual(int(h['status']), 400) # assert the exception content is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception('UnknownResponseType', 'AuthGetAuthExceptions'), self, ir)
def poll(sensor): # poll the data data = None log.debug("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "] polling sensor") try: # retrieve the raw data data = plugins[sensor['plugin']['plugin_name']].poll(sensor) # delete from the cache the previous value db.delete(sensor['db_cache']) # store it in the cache db.set(sensor["db_cache"], data, utils.now()) except Exception, e: log.warning("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "] unable to poll: " + utils.get_exception(e)) return None
def notify(severity,text): global current_hour, channels, counters # retrieve the current hour hour = int(time.strftime("%H")) # if this is a new hour, reset the notification counters if hour is None or current_hour != hour: for channel in channels: counters[channel] = 0 current_hour = hour # for each channel to be notified for channel,module in channels.iteritems(): # ensure realtime alerts are enabled if not conf["output"][channel]["enabled"]: continue mute_override = False min_severity = None mute_min_severity = None # ensure the severity is equals or above the minimum severity configured if "min_severity" in conf["output"][channel]: min_severity = conf["output"][channel]["min_severity"] if min_severity == "warning" and severity in ["info"]: continue elif min_severity == "alert" and severity in ["info","warning"]: continue # check if the notification is severe enough to override the mute setting if "mute_min_severity" in conf["output"][channel]: mute_min_severity = conf["output"][channel]["mute_min_severity"] if mute_min_severity == "warning" and severity in ["warning","alert"]: mute_override = True elif mute_min_severity == "alert" and severity in ["alert"]: mute_override = True # ensure the channel is not mute now if "mute" in conf["output"][channel] and "-" in conf["output"][channel]["mute"] and not mute_override: timeframe = conf["output"][channel]["mute"].split("-") if len(timeframe) != 2: continue timeframe[0] = int(timeframe[0]) timeframe[1] = int(timeframe[1]) # e.g. 08-12 if timeframe[0] < timeframe[1] and (hour >= timeframe[0] and hour < timeframe[1]): continue # e.g. 20-07 if timeframe[0] > timeframe[1] and (hour >= timeframe[0] or hour < timeframe[1]): continue # check if rate limit is configured and we have not exceed the numner of notifications during this hour if "rate_limit" in conf["output"][channel] and conf["output"][channel]["rate_limit"] != 0 and counters[channel] >= conf["output"][channel]["rate_limit"]: continue # increase the counter counters[channel] = counters[channel] + 1 log.debug(channel+" notifications: "+str(counters[channel])+" for "+str(current_hour)+":00") # send the notification to the channel try: # catch exceptions in order to notify even if a channel will fail module.notify(text) except Exception,e: log.error("unable to notify through "+channel+": "+utils.get_exception(e))
def test_negative_auth_get_auth_invalid_URI(self): """ Check exception raised while getting auth for uri, and verify the exception contains correct error messages. """ http = httplib2.Http() # construct invalid client id invalid_request = [utils.random_str()] for ir in invalid_request: logging.info("The invalid uri to be tested is '%s'" % str(ir)) url = urllib.quote('http://' + utils.auth_server + '/' + utils.auth_partner + '/authorize?' + 'response_type=token' + '&client_id=' + utils.auth_client_id + '&redirect_uri=' + ir, ':/&=?') logging.info("The requested url is '%s'" % url) h,c = http.request(url, 'GET', headers = utils.headers) logging.debug("The retrieved header is '%s'" % str(h)) logging.debug("The retrieved content is '%s'" % str(c)) # assert it's a bad request self.assertEqual(int(h['status']), 400) # assert the exception content is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception('UnmatchedURI', 'AuthGetAuthExceptions'), self)
def test_negative_auth_get_auth_empty_partner(self): """ Check exception raised while getting auth with empty partner, and verify the exception contains correct error messages. """ http = httplib2.Http() # construct invalid invalid partner invalid_partners= [' '] for ip in invalid_partners: logging.info("The invalid partner to be tested is '%s'" % str(ip)) url = urllib.quote('http://' + utils.auth_server + '/' + ip + '/authorize?' + 'response_type=token' + '&client_id=' + utils.auth_client_id, ':/&=') logging.info("The requested url is '%s'" % url) h,c = http.request(url, 'GET', headers = utils.headers) logging.debug("The retrieved header is '%s'" % str(h)) logging.debug("The retrieved content is '%s'" % str(c)) # assert it's a bad request self.assertEqual(int(h['status']), 500) # assert the exception content is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception('EmptySubdomain', 'AuthGetAuthExceptions'), self)
def test_negative_auth_get_config_invalid_client(self): """ Check exception raised while getting auth for invalid client, and verify the exception contains correct error messages. """ # get config headers = utils.headers # compose basic auth invalid_auth = ["Basic %s" % base64.encodestring('%s:%s' % (utils.auth_client_id, utils.random_str()))[:-1], "Basic %s" % base64.encodestring('%s:%s' % (utils.random_str(), utils.auth_client_secret))[:-1], "", " "] for ia in invalid_auth: headers['Authorization'] = ia logging.debug("The requested url is '%s'" % str(self.url)) logging.info("The invalid authentication head is '%s'" % ia) h, c = self.http.request(self.url, 'GET', headers = utils.headers) logging.debug("The response head is '%s'" % str(h)) logging.debug("The response body is '%s'" % str(c)) # assert status code is '400' self.assertEqual(int(h['status']), 400) # verify exception content is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception("UnknownClient", "AuthGetConfigExceptions"), self)
def test_negative_auth_post_token_empty_SAML(self): """ Check exception raised while posting token with empty SAML, and verify the exception contains correct error messages. """ headers = utils.headers # compose basic auth headers['Authorization'] = "Basic %s" % base64.encodestring('%s:%s' % (utils.auth_client_id, utils.auth_client_secret))[:-1] logging.debug("The requested header is '%s'" % str(headers)) # construct invalid responses invalid_SAML= [' ', ''] for ism in invalid_SAML: logging.info("The invalid SAML to be tested is '%s'" % str(ism)) logging.info("The requested url is '%s'" % self.url) # post token body = {'grant_type': 'http://oauth.net/grant_type/assertion/saml/2.0/bearer', 'assertion': ism} h, c = self.http.request(self.url, 'POST', headers = headers, body = urllib.urlencode(body)) # assert response head status is 400 self.assertEqual(int(h['status']), 400) # assert error msg is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception("EmptySAML", "AuthPostTokenExceptions"), self)
def test_negative_auth_get_config_empty_partner(self): """ Check exception raised while getting auth for empty partner, and verify the exception contains correct error messages. """ # get config headers = utils.headers # compose basic auth headers['Authorization'] = "Basic %s" % base64.encodestring('%s:%s' % (utils.auth_client_id, utils.auth_client_secret))[:-1] invalid_partners = [' '] for ip in invalid_partners: logging.info("The invalid partner is '%s'" % ip) url = urllib.quote('http://' + utils.auth_server + '/' + ip + '/config', ':/&=') logging.debug("The requested url is '%s'" % str(url)) h, c = self.http.request(url, 'GET', headers = utils.headers) logging.debug("The response head is '%s'" % str(h)) logging.debug("The response body is '%s'" % str(c)) # assert status code is '500' self.assertEqual(int(h['status']), 500) # verify exception content is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception("EmptySubdomain", "AuthGetConfigExceptions"), self)
def poll(sensor): # retrieve the image from a url if "url" in sensor["plugin"]: # set the parameters username = sensor['plugin']['username'] if 'username' in sensor[ 'plugin'] else None password = sensor['plugin']['password'] if 'password' in sensor[ 'plugin'] else None # visit the page try: data = utils.web_get(sensor['plugin']['url'], username, password, binary=True, timeout=conf["plugins"]["image"]["timeout"]) except Exception, e: log.debug("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "] unable to visit " + sensor['plugin']['url'] + ": " + utils.get_exception(e)) return ""
def test_negative_auth_post_token_invalid_grant_type(self): """ Check exception raised while posting token with invalid grant_type, and verify the exception contains correct error messages. """ headers = utils.headers # compose basic auth headers['Authorization'] = "Basic %s" % base64.encodestring('%s:%s' % (utils.auth_client_id, utils.auth_client_secret))[:-1] logging.debug("The requested header is '%s'" % str(headers)) # construct invalid responses invalid_grant_type= [utils.random_str(), ' ', ''] for ig in invalid_grant_type: logging.info("The invalid grant_type to be tested is '%s'" % str(ig)) logging.info("The requested url is '%s'" % self.url) # post token body = {'grant_type': ig, 'assertion': utils.SAMLResponse} h, c = self.http.request(self.url, 'POST', headers = headers, body = urllib.urlencode(body)) # assert response head status is 400 self.assertEqual(int(h['status']), 400) # assert error msg is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception("UnsupportedGrantType", "AuthPostTokenExceptions"), self)
def run(module_id, group_id, sensor_id, action): try: # ensure the group and sensor exist sensor = utils.get_sensor(module_id, group_id, sensor_id) sensor = init_sensor(sensor) if sensor is None: log.error("[" + module_id + "][" + group_id + "][" + sensor_id + "] not found, skipping it") return # execute the action log.debug("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "] requested " + action) if action == "poll": # read the measure (will be stored into the cache) poll(sensor) elif action == "parse": # just parse the output log.info(parse(sensor)) elif action == "save": # save the parsed output into the database save(sensor) elif action == "force_save": # save the parsed output into the database forcing polling the measure save(sensor, force=True) elif action == "summarize_hour": # every hour calculate and save min,max,avg of the previous hour summarize(sensor, 'hour', utils.hour_start(utils.last_hour()), utils.hour_end(utils.last_hour())) elif action == "summarize_day": # every day calculate and save min,max,avg of the previous day (using hourly averages) summarize(sensor, 'day', utils.day_start(utils.yesterday()), utils.day_end(utils.yesterday())) elif action == "expire": # purge old data from the database expire(sensor) else: log.error("Unknown action " + action) except Exception, e: log.warning("[" + sensor["module_id"] + "][" + sensor["group_id"] + "][" + sensor["sensor_id"] + "] unable to run " + action + ": " + utils.get_exception(e))
def test_negative_auth_post_token_empty_partner(self): """ Check exception raised while getting auth for empty partner, and verify the exception contains correct error messages. """ # get config headers = utils.headers # compose basic auth headers['Authorization'] = "Basic %s" % base64.encodestring('%s:%s' % (utils.auth_client_id, utils.auth_client_secret))[:-1] body = {'grant_type': 'http://oauth.net/grant_type/assertion/saml/2.0/bearer', 'assertion': utils.SAMLResponse} invalid_partners = [' '] for ip in invalid_partners: logging.info("The invalid partner is '%s'" % ip) url = urllib.quote('http://' + utils.auth_server + '/' + ip + '/token', ':/&=') logging.debug("The requested url is '%s'" % str(url)) h, c = self.http.request(url, 'POST', headers = utils.headers, body = urllib.urlencode(body)) logging.debug("The response head is '%s'" % str(h)) logging.debug("The response body is '%s'" % str(c)) # assert status code is '400' self.assertEqual(int(h['status']), 400) # verify exception content is correct utils.verify_rest_requetfailed_exception(c, utils.get_exception("InvalidSubdomain", "AuthPostTokenExceptions"), self)
def slack_message(channel,message): try: slack.api_call("chat.postMessage",channel=channel,text=message,as_user=True) except Exception,e: log.warning("unable to post message to slack: "+utils.get_exception(e))
if '"SOUNDER",0' in line or '"CALL",0' in line: log.info("Called " + str(to)) done = True if "ERROR" in line: done = True break if done: break i = i - 1 if i == 0: # timeout reached log.error("Unable to call " + str(to) + ": timeout reached") break except Exception, e: log.error("Failed to call " + str(to) + ": " + utils.get_exception(e)) # disconect modem.close() # make a call def make_call(modem, to, duration): log.debug("Calling " + str(to)) time.sleep(2) # place the call modem.write(b'ATD' + to + '\r') # make the phone ring for the configured tie time.sleep(duration) # hung up modem.write(b'ATH\r')
def run(): if not plugin_conf["enabled"]: return log.debug("[" + __name__ + "] listening for UDP datagrams on port " + str(plugin_conf['port_listen'])) # bind to the network sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sock.bind(("", plugin_conf['port_listen'])) while True: try: # new data arrives data, addr = sock.recvfrom(1024) log.debug("[" + __name__ + "] received " + data) data = json.loads(data) if data["type"] != "WirelessMessage": continue # check if it belongs to a registered sensor if data["id"] not in nodes: continue node = nodes[data["id"]] # for each measure for message in data["data"]: if message == "STARTED": if default_measure not in node: continue sensor = node[default_measure] log.info("[" + sensor["module_id"] + "][" + sensor["sensor_id"] + "] has just started") # ACK a started message tx(sensor, "ACK", True) # initialize init(sensor) if message == "AWAKE": if default_measure not in node: continue sensor = node[default_measure] # send a message if there is something in the queue if data["id"] in queue and len(queue[data["id"]]) > 0: tx(sensor, queue[data["id"]]) queue[data["id"]] = [] # put it to sleep again sleep(sensor) # other messages can be a measure from the sensor measures = [] # for each registered measure for this node_id for measure, sensor in node.iteritems(): # skip if not a registered measure if not message.startswith(measure): continue measure_data = {} # generate the timestamp date = datetime.datetime.strptime( data["timestamp"], "%d %b %Y %H:%M:%S +0000") measure_data["timestamp"] = utils.timezone( utils.timezone(int(time.mktime(date.timetuple())))) measure_data["key"] = sensor["sensor_id"] # strip out the measure from the value measure_data["value"] = utils.normalize( message.replace(measure, ""), conf["constants"] ["formats"][sensor["format"]]["formatter"]) measures.append(measure_data) sensors.store(sensor, measures) except Exception, e: log.warning("unable to parse " + str(data) + ": " + utils.get_exception(e))
class Gateway(): def __init__(self, gateway_conf): # gateway settings self.gateway_conf = gateway_conf self.gateway_type = gateway_conf["gateway_type"] self.gateway_id = gateway_conf["gateway_id"] # variable to store the gateway object self.gateway = None # keep track if we are connected to the gateway self.connected = False # queue of messages for sleeping nodes self.queue = {} # data structure for storing registered sensors' information # nodes[<node_id>][<child_id>][<command>][<type>] = sensor # e.g. nodes["254"]["1"]["1"]["V_TEMP"] = sensor self.nodes = {} # data structure for storing the assigned node IDs self.assigned_ids = [] # the database key where assigned node IDs are stored self.assigned_ids_key = conf["constants"]["db_schema"][ "tmp"] + ":plugin_mysensors:" + self.gateway_id + ":assigned_ids" # register a myHouse sensor agains this gateway def register_sensor(self, sensor): node_id = sensor["plugin"]["node_id"] child_id = sensor["plugin"]["child_id"] command_string = sensor["plugin"]["command"] type_string = sensor["plugin"]["type"] # create a data structure for each node_id if node_id not in self.nodes: self.nodes[node_id] = {} # create a data structure for each child_id if child_id not in self.nodes[node_id]: self.nodes[node_id][child_id] = {} # create a data structure for each command if command_string not in self.nodes[node_id][child_id]: self.nodes[node_id][child_id][command_string] = {} # check if the type has already been registered if type_string in self.nodes[node_id][child_id][command_string]: log.warning("[" + self.gateway_id + "][" + str(node_id) + "][" + str(child_id) + "][" + command_string + "][" + type_string + "] already registered, skipping") return # add the sensor to the nodes list self.nodes[node_id][child_id][command_string][type_string] = sensor log.debug("[" + self.gateway_id + "][" + str(node_id) + "][" + str(child_id) + "][" + command_string + "][" + type_string + "] registered sensor " + sensor['module_id'] + ":" + sensor['group_id'] + ":" + sensor['sensor_id']) # run the service def run(self): log.info("[" + self.gateway_id + "] starting mysensors " + self.gateway_type + " gateway") # load previously assigned node ids if db.exists(self.assigned_ids_key): self.assigned_ids = db.rangebyscore(self.assigned_ids_key, "-inf", "+inf", withscores=False) errors = 0 while True: # connect to the configured gateway if not self.connected: self.connected = self.connect() if not self.connected: # something went wrong while connecting, sleep for a while and then try again time.sleep(sleep_on_error) continue if self.gateway_type == "serial" or self.gateway_type == "ethernet": # for serial and ethernet manage the loop manually by reading every single message message = self.read() if message is None: # something went wrong while reading the message, increase the error counter errors = errors + 1 time.sleep(1) if errors > 10: # too many consecutive errors, sleep for a while and then try to reconnect log.error( "[" + self.gateway_id + "] Too many errors, will try reconnecting in a while" ) time.sleep(sleep_on_error) self.connected = False # go and read a new message continue # parse the message parsed = self.parse(message) if parsed is None: # something went wrong while parsing the message, increase the error counter errors = errors + 1 time.sleep(1) if errors > 10: # too many consecutive errors, sleep for a while and then try to reconnect log.error( "[" + self.gateway_id + "] Too many errors, will try reconnecting in a while" ) time.sleep(sleep_on_error) self.connected = False # go and read a new message continue # parsed correctly, reset the error counter errors = 0 elif self.gateway_type == "mqtt": # for mqtt the loop is managed automatically with callbacks self.gateway.loop() # the loop should never end, if it will, sleep for a while then try to reconnect time.sleep(sleep_on_error) self.connected = False continue # connect to the gateway def connect(self): if self.gateway_type == "serial": try: # connect to the serial gateway log.info("[" + self.gateway_id + "] Connecting to serial gateway on " + self.gateway_conf["port"] + " with baud rate " + str(self.gateway_conf["baud"])) self.gateway = serial.Serial(self.gateway_conf["port"], self.gateway_conf["baud"]) except Exception, e: log.error("[" + self.gateway_id + "] Unable to connect to the serial gateway: " + utils.get_exception(e)) return False elif self.gateway_type == "ethernet": try: # connect to the ethernet gateway log.info("[" + self.gateway_id + "] Connecting to ethernet gateway on " + self.gateway_conf["hostname"] + ":" + str(self.gateway_conf["port"])) self.gateway = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.gateway.connect( (self.gateway_conf["hostname"], self.gateway_conf["port"])) except Exception, e: log.error("[" + self.gateway_id + "] Unable to connect to the ethernet gateway: " + utils.get_exception(e)) return False
def slack_upload(channel,filename,title): try: slack.api_call("files.upload",channels=channel,filename=filename,file=open(filename,'rb'),title=title) except Exception,e: log.warning("unable to upload file to slack: "+utils.get_exception(e))