Ejemplo n.º 1
0
 def stop_module(self, entry):
     if not entry["started"]: return
     try:
         self.threads[entry["fullname"]].join()
     except Exception, e:
         print "Error while stopping module " + entry[
             "fullname"] + ": " + exception.get(e)
Ejemplo n.º 2
0
 def load_default_config(self):
     config_dir = "default_config"
     default_config = []
     if not os.path.isdir(config_dir): return default_config
     # walk through the filesystem containing the default configuration
     for (current_path, dirnames, filenames) in os.walk(config_dir):
         for filename in filenames:
             if filename[0] == ".": continue
             file = current_path + os.sep + filename
             # parse the file paths
             name, extension = os.path.splitext(file)
             if extension != ".yml": continue
             # remove base configuration dir to build the topic
             topic = name.replace(config_dir + os.sep, "")
             # if aliases are used, alter the filename if it is matching
             config_file, config_version = topic.split(".")
             if config_file in self.aliases:
                 topic = self.aliases[config_file] + "." + config_version
             # read the file's content
             with open(file) as f:
                 content = f.read()
             # ensure the yaml file is valid
             try:
                 content = yaml.load(content, Loader=yaml.SafeLoader)
             except Exception, e:
                 self.log_warning(
                     "configuration file in an invalid YAML format: " +
                     filename + " - " + exception.get(e))
                 continue
             # keep track of the valid configuration file
             default_config.append({topic: content})
 def on_message(client, userdata, msg):
     try:
         self.log_debug("received mqtt message on " +
                        str(msg.topic))
         # find the sensor matching the topic
         for sensor_id in self.sensors:
             configuration = self.sensors[sensor_id]
             # exclude pull sensors
             if "topic" not in configuration:
                 continue
             # if the message is for this sensor
             if msg.topic == str(configuration["topic"]):
                 image = msg.payload
                 self.log_debug("received an image for " +
                                sensor_id)
                 # analyze the image
                 image = self.analyze_image(sensor_id,
                                            configuration, image)
                 if image is None:
                     return
                 image = base64.b64encode(image)
                 # prepare the message
                 message = Message(self)
                 message.recipient = "controller/hub"
                 message.command = "IN"
                 message.args = sensor_id
                 message.set("value", image)
                 # send the message to the controller
                 self.send(message)
                 break
     except Exception, e:
         self.log_error("Unable to process mqtt message: " +
                        exception.get(e))
Ejemplo n.º 4
0
 def on_start(self):
     # ensure config path exists, otherwise create it
     if not os.path.exists(self.config_dir):
         try:
             os.makedirs(self.config_dir)
         except Exception,e: 
             self.log_error("unable to create directory "+self.config_dir+": "+exception.get(e))
Ejemplo n.º 5
0
 def on_message(self, message):
     if message.command == "IN":
         sensor_id = message.args
         # ensure configuration is valid
         if not self.is_valid_configuration(["url"], message.get_data()): return
         url = message.get("url")
         # if the raw data is cached, take it from there, otherwise request the data and cache it
         cache_key = "/".join([url])
         if self.cache.find(cache_key): 
             data = self.cache.get(cache_key)
         else:
             try:
                 data = sdk.python.utils.web.get(url)
             except Exception,e: 
                 self.log_error("unable to connect to "+csv_file+": "+exception.get(e))
                 return
             self.cache.add(cache_key, data)
         message.reply()
         # parse the feed
         feed = feedparser.parse(data)
         result = ""
         for i in range(len(feed["entries"])):
             entry = feed["entries"][i]
             # return a single string containing all the entries
             result = result + entry["title"].encode('ascii','ignore')+"\n"
         message.set("value", result)
         # send the response back
         self.send(message)
Ejemplo n.º 6
0
 def connect(self):
     hostname = self.module.hostname if self.module.hostname is not None else self.module.config[
         "hostname"]
     port = self.module.port if self.module.port is not None else self.module.config[
         "port"]
     database = self.module.database if self.module.database is not None else self.module.config[
         "database"]
     password = None
     if "password" in self.module.config:
         password = self.module.config["password"]
     if self.module.password is not None: password = self.module.password
     while not self.connected:
         try:
             self.module.log_debug("Connecting to database " +
                                   str(database) + " at " + hostname + ":" +
                                   str(port))
             self.db = redis.StrictRedis(host=hostname,
                                         port=port,
                                         db=int(database),
                                         password=password)
             if self.db.ping():
                 self.db_version = self.db.info().get('redis_version')
                 self.module.log_info("Connected to database #" +
                                      str(database) + " at " + hostname +
                                      ":" + str(port) + ", redis version " +
                                      self.db_version)
                 self.connected = True
         except Exception, e:
             self.module.log_error("Unable to connect to " + hostname +
                                   ":" + str(port) + " - " +
                                   exception.get(e))
             self.module.sleep(5)
             if self.module.stopping: break
 def on_message(self, message):
     if message.command == "IN":
         if not self.is_valid_configuration(
             ["request", "latitude", "longitude"], message.get_data()):
             return
         sensor_id = message.args
         request = message.get("request")
         location = "lat=" + str(message.get("latitude")) + "&lon=" + str(
             message.get("longitude"))
         # if the raw data is cached, take it from there, otherwise request the data and cache it
         cache_key = location
         if self.cache.find(cache_key):
             data = self.cache.get(cache_key)
         else:
             url = self.url + "?" + location
             try:
                 data = sdk.python.utils.web.get(url)
             except Exception, e:
                 self.log_error("unable to connect to " + url + ": " +
                                exception.get(e))
                 return
             self.cache.add(cache_key, data)
         # parse the raw data
         try:
             parsed_json = json.loads(data)
         except Exception, e:
             self.log_error("invalid JSON returned")
             return
Ejemplo n.º 8
0
 def slack_init(self):
     if self.slack_initialized: return
     self.log_debug("Initializing slack...")
     # initialize the library
     try:
         # initialize the library
         self.slack = SlackClient(self.config["bot_token"])
         # test the authentication
         auth = self.slack.api_call("auth.test")
         if not auth["ok"]:
             self.log_error("authentication failed: " + auth["error"])
             return
         # retrieve the bot id
         self.bot_id = self.get_user_id(self.config["bot_name"])
         if self.bot_id is None:
             self.log_error("unable to find your bot " +
                            self.config["bot_name"] +
                            ". Ensure it is configured correctly")
             return
         # retrieve the channel id
         self.channel_id = self.get_channel_id(self.config["channel"])
         if self.channel_id is None:
             self.log_error("unable to find the channel " +
                            self.config["channel"])
             return
         self.slack_initialized = True
     except Exception, e:
         self.log_warning("unable to initialize slack: " + exception.get(e))
Ejemplo n.º 9
0
 def tx(self,
        node_id,
        child_id,
        command_string,
        type_string,
        payload,
        ack=0,
        system_message=False):
     # map the correspoding command and type
     command = self.commands.index(command_string)
     type = self.types[command].index(type_string)
     ack_string = self.acks[ack]
     if not system_message:
         self.log_info("[" + str(node_id) + "][" + str(child_id) + "][" +
                       command_string + "][" + type_string +
                       "] sending message: " + str(payload))
     # 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:
         self.log_error("unable to send " + str(msg) +
                        " to the serial gateway: " + exception.get(e))
Ejemplo n.º 10
0
 def connect(self):
     hostname = self.module.hostname if self.module.hostname is not None else self.module.config[
         "hostname"]
     port = self.module.port if self.module.port is not None else self.module.config[
         "port"]
     database = self.module.database if self.module.database is not None else self.module.config[
         "database"]
     username = self.module.username if self.module.username is not None else self.module.config[
         "username"]
     password = self.module.password if self.module.password is not None else self.module.config[
         "password"]
     while not self.connected:
         try:
             self.module.log_debug("Connecting to database " +
                                   str(database) + " at " + hostname + ":" +
                                   str(port))
             self.client = pymongo.MongoClient("mongodb://" + username +
                                               ":" + password + "@" +
                                               hostname + ":" + str(port) +
                                               "/" + str(database))
             self.db = self.client[database]
             self.db_version = str(self.client.server_info()["version"])
             self.module.log_info("Connected to database " + str(database) +
                                  " at " + hostname + ":" + str(port) +
                                  ", mongodb version " + self.db_version)
             self.connected = True
         except Exception, e:
             self.module.log_error("Unable to connect to " + hostname +
                                   ":" + str(port) + " - " +
                                   exception.get(e))
             self.module.sleep(5)
             if self.module.stopping: break
Ejemplo n.º 11
0
 def __on_disconnect(client, userdata, rc):
     self.module.connected = False
     # call user's callback
     try: 
         self.module.on_disconnect()
     except Exception,e: 
         self.module.log_error("runtime error during on_disconnect(): "+exception.get(e))
Ejemplo n.º 12
0
 def send_sms(self, to, text):
     protocol = "https://" if self.config["ssl"] else "http://"
     url = protocol+self.config["hostname"]+"/myaccount/sendsms.php?username="******"username"]+"&password="******"password"]+"&from="+str(self.config["from"])+"&to="+str(to)+"&text="+text
     try: 
         response = sdk.python.utils.web.get(url)
     except Exception,e:
         self.log_warning("unable to connect to the sms module: "+exception.get(e))
         return False
 def on_notify(self, severity, text):
     # connect to the modem
     try:
         self.log_debug("Connecting to GSM modem on port "+self.config["port"]+" with baud rate "+str(self.config["baud"]))
         modem = serial.Serial(self.config["port"], self.config["baud"], timeout=0.5)
     except Exception,e:
         self.log_error("Unable to connect to the GSM modem: "+exception.get(e))
         return
 def on_message(client, userdata, msg):
     try:
         self.log_debug("received "+str(msg.topic)+": "+str(msg.payload))
         # split the topic
         topic, node_id, child_id, command, ack, type = msg.topic.rsplit("/", 5)
     except Exception,e:
         self.log_error("Invalid format ("+msg.topic+"): "+exception.get(e))
         return
 def parse(self, message):
     self.log_debug("received " + str(message))
     # parse the message
     try:
         node_id, child_id, command, ack, type, payload = message.split(";")
     except Exception, e:
         self.log_debug("Invalid format (" + message + "): " +
                        exception.get(e))
         return None
 def on_start(self):
     self.log_debug("listening for UDP datagrams on port " +
                    str(self.config["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(("", self.config["port_listen"]))
     while True:
         try:
             # new data arrives
             data, addr = sock.recvfrom(1024)
             self.log_debug("received " + data)
             # the message is expected to be in JSON format
             data = json.loads(data)
             if data["type"] != "WirelessMessage": continue
             # parse content
             content = data["data"][0]
             # sensor just started
             if content == "STARTED":
                 self.log_info(data["id"] + " has just started")
                 self.tx(data["id"], "ACK", True)
             elif content == "AWAKE":
                 # send a message if there is something in the queue
                 if data["id"] in self.queue and len(
                         self.queue[data["id"]]) > 0:
                     self.tx(data["id"], queue[data["id"]])
                     self.queue[data["id"]] = []
             else:
                 # look for the sensor_id associated to this measure
                 sensor = None
                 for sensor_id in self.sensors:
                     if data["id"] == self.sensors[sensor_id][
                             "node_id"] and content.startswith(
                                 self.sensors[sensor_id]["measure"]):
                         sensor = self.sensors[sensor_id]
                         break
                 # if not registered, skip it
                 if sensor is None: continue
                 # prepare the message
                 message = Message(self)
                 message.recipient = "controller/hub"
                 message.command = "IN"
                 message.args = sensor_id
                 # generate the timestamp
                 # date_in = datetime.datetime.strptime(data["timestamp"],"%d %b %Y %H:%M:%S +0000")
                 # message.set("timestamp", int(time.mktime(date_in.timetuple())))
                 # strip out the measure from the value
                 message.set(
                     "value",
                     content.replace(self.sensors[sensor_id]["measure"],
                                     ""))
                 # send the measure to the controller
                 self.send(message)
         except Exception, e:
             self.log_warning("unable to parse " + str(data) + ": " +
                              exception.get(e))
Ejemplo n.º 17
0
 def read(self):
     line = ""
     # read a line
     try:
         line = self.gateway.readline().rstrip()
     except Exception, e:
         self.log_error("Unable to receive data from the serial gateway: " +
                        exception.get(e))
         return None
 def on_start(self):
     self.log_info("Starting mysensors MQTT gateway")
     # connect to the mqtt broker
     self.connect()
     # start loop (in the background)
     # TODO: reconnect
     try: 
         self.gateway.loop_start()
     except Exception,e: 
         self.log_error("Unexpected runtime error: "+exception.get(e))
Ejemplo n.º 19
0
 def slack_message(self, message):
     # TODO: image
     try:
         self.slack.api_call("chat.postMessage",
                             channel=self.channel_id,
                             text=message,
                             as_user=True)
     except Exception, e:
         self.log_warning("unable to post message to slack: " +
                          exception.get(e))
 def connect(self):
     try:
         # connect to the ethernet gateway
         self.log_info("Connecting to ethernet gateway on "+self.config["hostname"]+":"+str(self.config["port"]))
         self.gateway = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         self.gateway.connect((self.config["hostname"], self.config["port"]))
         return True
     except Exception,e:
         self.log_error("Unable to connect to the ethernet gateway: "+exception.get(e))
         return False
Ejemplo n.º 21
0
 def get_manifest(self, manifest_file):
     if not os.path.isfile(manifest_file):
         raise Exception(manifest_file + " not found")
     with open(manifest_file) as f:
         content = f.read()
     # ensure the manifest is valid
     try:
         manifest = yaml.load(content, Loader=yaml.SafeLoader)
     except Exception, e:
         raise Exception(manifest_file + " is an invalid manifest:- " +
                         exception.get(e))
Ejemplo n.º 22
0
 def slack_message(self, channel, message):
     if not self.slack_connected: return
     # TODO: image
     try:
         self.slack.api_call("chat.postMessage",
                             channel=channel,
                             text=message,
                             as_user=True)
     except Exception, e:
         self.log_warning("unable to post message to slack: " +
                          exception.get(e))
Ejemplo n.º 23
0
 def __remove_schedule(self, sensor_id):
     # if already scheduled, stop it
     if sensor_id in self.__jobs:
         try:
             for job in self.__scheduler.get_jobs():
                 if job.id == self.__jobs[sensor_id]:
                     self.__scheduler.remove_job(self.__jobs[sensor_id])
         except Exception, e:
             self.log_error("Unable to remove scheduled job for sensor " +
                            sensor_id + ": " + exception.get(e))
         del self.__jobs[sensor_id]
Ejemplo n.º 24
0
 def on_message(self, message):
     # requested to update/save a configuration file
     if message.command == "SAVE":
         if self.parse_topic(message.args) is None: return
         version, filename = self.parse_topic(message.args)
         self.save_config_file(filename, version, message.get_data())
     # requested to delete a configuration file
     elif message.command == "DELETE":
         if self.parse_topic(message.args) is None: return
         version, filename = self.parse_topic(message.args)
         self.delete_config_file(filename, version)
     # requested to rename a configuration file
     elif message.command == "RENAME":
         if self.parse_topic(message.args) is None: return
         version, from_filename = self.parse_topic(message.args)
         to_filename = message.get_data()
         self.rename_config_file(from_filename, to_filename, version)
     # receive manifest file, it may contain default configurations
     elif message.command == "MANIFEST":
         if message.is_null: return
         manifest = message.get_data()
         if manifest["manifest_schema"] != self.supported_manifest_schema:
             return
         self.log_debug("Received manifest from " + message.sender)
         if not self.accept_default_config or self.force_reload or not "default_config" in manifest:
             return
         # if there is a default configuration in the manifest file, save it
         default_config = manifest["default_config"]
         for entry in default_config:
             for filename_with_version in entry:
                 if self.parse_filename(filename_with_version) is None:
                     return
                 filename, version = self.parse_filename(
                     filename_with_version)
                 file_content = entry[filename_with_version]
                 # do not overwrite existing files since the user may have changed default values
                 # for updated configurations, prevent saving the new version, letting the module managing the upgrade
                 if filename in self.old_index: continue
                 # ensure the file is in a valid YAML format
                 try:
                     content = yaml.safe_dump(file_content,
                                              default_flow_style=False)
                 except Exception, e:
                     self.log_warning("unable to save " + filename +
                                      ", invalid YAML format: " +
                                      str(file_content) + " - " +
                                      exception.get(e))
                     return
                 # save the new/updated default configuration file
                 self.log_debug("Received new default configuration file " +
                                filename)
                 self.save_config_file(filename, version, file_content,
                                       False)
                 self.reload_config()
Ejemplo n.º 25
0
 def connect(self):
     try:
         # connect to the serial gateway
         self.log_info("Connecting to serial gateway on " +
                       self.config["port"] + " with baud rate " +
                       str(self.config["baud"]))
         self.gateway = serial.Serial(self.config["port"],
                                      self.config["baud"])
         return True
     except Exception, e:
         self.log_error("Unable to connect to the serial gateway: " +
                        exception.get(e))
         return False
 def tx(self, node_id, child_id, command_string, type_string, payload, ack=0, system_message=False):
     # map the correspoding command and type
     command = self.commands.index(command_string)
     type = self.types[command].index(type_string)
     ack_string = self.acks[ack]
     if not system_message: self.log_info("["+str(node_id)+"]["+str(child_id)+"]["+command_string+"]["+type_string+"] sending message: "+str(payload))
     # publish the payload to the mqtt broker
     topic = self.config["publish_topic_prefix"]+"/"+str(node_id)+"/"+str(child_id)+"/"+str(command)+"/"+str(ack)+"/"+str(type)
     self.log_debug("publishing on topic "+topic+": "+str(payload))
     try: 
         self.gateway.publish(topic, str(payload))
     except Exception,e:
         self.log_error("unable to publish "+str(payload)+" on topic "+topic+": "+exception.get(e))
 def read(self):
     # read a line
     try:
         line = ""
         while True:
             c = self.gateway.recv(1)
             # identify broken connections
             if not c: return None
             if c == '\n' or c == '': break
             else: line += c
     except Exception,e:
         self.log_error("Unable to receive data from the ethernet gateway: "+exception.get(e))
         return None
Ejemplo n.º 28
0
 def save_config_file(self, file, version, data, reload_after_save=True):
     # ensure filename is valid
     if ".." in file:
         self.log_warning("invalid file " + file)
         return
     content = None
     # ensure the file is in the correct format
     try:
         content = yaml.safe_dump(data, default_flow_style=False)
     except Exception, e:
         self.log_warning("unable to save " + file +
                          ", invalid YAML format: " + str(data) + " - " +
                          exception.get(e))
         return
Ejemplo n.º 29
0
 def stop(self):
     # stop all message consumer threads
     for consumer in self.consumers:
         consumer.join()
     # do nothing if not connected to the gateway
     if self.gateway == None: return
     # stop the mqtt network thread
     self.gateway.loop_stop()
     # disconnect from the gateway
     self.gateway.disconnect()
     try:
         self.module.on_disconnect()
     except Exception,e: 
         self.module.log_error("runtime error during on_disconnect(): "+exception.get(e))
Ejemplo n.º 30
0
 def slack_image(self, channel, message, title):
     # save the file first since when using content= the filetype is not inferred correctly
     f = open(self.tmp_file, "w")
     f.write(base64.b64decode(message))
     f.close()
     # upload the file
     try:
         self.slack.api_call("files.upload",
                             channels=channel,
                             file=open(self.tmp_file, 'rb'),
                             filename=self.tmp_file,
                             title=title)
     except Exception, e:
         self.log_warning("unable to upload file to slack: " +
                          exception.get(e))