Example #1
0
class HeatX(driver.SmapDriver):
    def setup(self, opts):
        host = opts.get("Host", "10.0.50.118")
        self.rate = int(opts.get("Rate", 20))
        self.modbus = ModbusTCP(host)
        self.add_timeseries('/energy0', 'BTU', data_type="double")
        self.add_timeseries('/energy1', 'BTU', data_type="double")
        self.add_timeseries('/accum0', 'BTU', data_type="double")
        self.add_timeseries('/accum1', 'BTU', data_type="double")
        self.add_timeseries('/volume', 'ga', data_type="double")
        self.add_timeseries('/accum_volume', 'ga', data_type="double")
        self.add_timeseries('/power', 'BTU/hr', data_type="double")
        self.add_timeseries('/vol_flow', 'ga/min', data_type="double")
        self.add_timeseries('/temp_flow', 'f', data_type="double")
        self.add_timeseries('/temp_return', 'f', data_type="double")
        self.add_timeseries('/tdelta', 'f', data_type="double")
        self.set_metadata(
            '/', {
                'Instrument/Manufacturer': 'Central Station Steam Co.',
                'Instrument/Model': 'Cadillac HEATX BTU Meter'
            })

    def start(self):
        util.periodicSequentialCall(self.update).start(self.rate)

    def update(self):
        try:
            data = self.modbus.read(25, 36)
        except IOError, e:
            log.err("Exception while reading device: " + str(e))
            return
        if data == None:
            log.err("Failed to read device\n")
            return
        s = ""
        try:
            for i in range(0, len(data), 4):
                s += data[i + 1]
                s += data[i + 0]
                s += data[i + 3]
                s += data[i + 2]
            vals = struct.unpack("<18f", s)
        except:
            return

        t = util.now()

        self.add("/energy0", t, vals[0])
        self.add("/energy1", t, vals[1])
        self.add("/accum0", t, vals[2])
        self.add("/accum1", t, vals[3])
        self.add("/volume", t, vals[4])
        self.add("/accum_volume", t, vals[5])

        self.add("/power", t, vals[10])
        self.add("/vol_flow", t, vals[12])
        self.add("/temp_flow", t, vals[14])
        self.add("/temp_return", t, vals[15])
        self.add("/tdelta", t, vals[16])
Example #2
0
 def newreading():
     global counter
     #print '-'*50
     s.get_collection('/')['Metadata']['Location'] = {'Room': counter}
     s.get_collection('/').dirty_children()
     for i in xrange(0, 1):
         #             s.get_timeseries('/sensor0')._add(util.now(), counter)
         #             s.get_timeseries('/sensor1')._add(counter)
         s._add('/sensor0', util.now(), counter)
         s._add('/sensor1', counter)
         counter += 1
Example #3
0
File: server.py Project: ahaas/smap
    def newreading():
        global counter
        #print '-'*50
        s.get_collection('/')['Metadata']['Location'] = {'Room' : counter}
        s.get_collection('/').dirty_children()
        for i in xrange(0, 1):
#             s.get_timeseries('/sensor0')._add(util.now(), counter)
#             s.get_timeseries('/sensor1')._add(counter)
            s._add('/sensor0', util.now(), counter)
            s._add('/sensor1', counter)
            counter += 1
Example #4
0
    def _finish_render(self, request, state):
        # finish by adding the current state as the reading
        if isinstance(state, dict):
            return state
        elif hasattr(state, "__iter__"):
            now, val = state
        else:
            now, val = util.now() * 1000, state

        try:
            val = self.impl.translate_state(state)
        except Exception, e:
            raise SmapException("Error processing write result: " + str(e), 500)
Example #5
0
    def _finish_render(self, request, state):
        # finish by adding the current state as the reading
        if isinstance(state, dict):
            return state
        elif hasattr(state, "__iter__"):
            now, val = state
        else:
            now, val = util.now() * 1000, state

        try:
            val = self.impl.translate_state(state)
        except Exception, e:
            raise SmapException("Error processing write result: " + str(e), 500)
Example #6
0
    def add_job(self, job):
        j = SmapJob(job)
        if 'StartTime' in job:
            start = job['StartTime'] / 1000.
            wait = start - util.now()
        else:
            wait = 0
        assert wait >= 0
        actions = j.actions
        if j.after:
            previous_job = util.find(lambda x: x.name == j.after, self.jobs)
            if previous_job is None:
                raise util.SmapException("No job named %s") % j.after
            else:
                j.d_outer = previous_job.d_outer
                j.job_id = previous_job.job_id
                j.uuid = job['uuid']
                self._job_ids[j.uuid] = j.job_id
        else: # assign it its own deferred
            j.d_outer = defer.Deferred()

        # closure that will carry out all of the job's actions
        def act(_):
            for action in actions:
                path = action['Path']
                state = action['State']
                actuator = self.inst.get_timeseries(path)
                print 'Setting', path, 'to', state
                actuator.impl.set_state(None, state)

        # queue the callback
        j.d_outer.addCallback(act)
        print 'Added callback to', j.d_outer

        if not j.after:
            # job_id will let you cancel it
            j.job_id = reactor.callLater(wait, j.d_outer.callback, None)
            self._job_ids[job['uuid']] = j.job_id
        self.jobs.append(j)

        return j.d_outer
Example #7
0
    def _add(self, *args):
        """Add a new reading to this timeseries.  This version must
only be called from the :py:mod:`twisted` main loop; *i.e.* from a
callback added with ``reactor.callFromThread()``

Can be called with 1, 2, or 3 arguments.  The forms are

* ``_add(value)``
* ``_add(time, value)``
* ``_add(time, value, seqno)``

:raises SmapException: if the value's type does not match the stream
 type, or was called with an invalid number of arguments.
        """
        seqno = None
        if len(args) == 1:
            time = util.now()
            if self.milliseconds: time *= 1000
            value = args[0]
        elif len(args) == 2:
            time, value = args
        elif len(args) == 3:
            time, value, seqno = args
        else:
            raise SmapException("Invalid add arguments: must be (value), "
                                "(time, value), or (time, value, seqno)")

        # note that we got data now
        self.inst.statslog.mark()

        time = int(time)
        if not self.milliseconds:
            time *= 1000

        if not self._check_type(value):
            raise SmapException("Attempted to add " + str(value) +
                                " to Timeseries, but " +
                                "the timeseries type is " +
                                self.__getitem__('Properties')['ReadingType'])

        if seqno: reading = time, value, seqno
        else: reading = time, value
        self["Readings"].append(reading)
        if not hasattr(self, 'inst'): return

        # if a timeseries is dirty, we need to republish all of its
        # metadata before we publish it so stream is right. some of
        # this may have already been published, in which case it won't
        # actually do anything.
        if self.dirty:
            split_path = util.split_path(getattr(self, 'path'))
            for i in xrange(0, len(split_path)):
                path_seg = util.join_path(split_path[:i])
                self.inst.reports.publish(path_seg,
                                          self.inst.get_collection(path_seg))
            rpt = dict(self)
            rpt['Readings'] = [reading]
            self.inst.reports.publish(getattr(self, 'path'), rpt)
            self.dirty = False
        else:
            # publish a stripped-down Timeseries object
            self.inst.reports.publish(getattr(self, 'path'), {
                'uuid': self['uuid'],
                'Readings': [reading]
            })
Example #8
0
    def pause_reporting(self):
        return self.reports.pause()

    def unpause_reporting(self):
        return self.reports.unpause()

if __name__ == '__main__':
    ROOT_UUID = uuid.uuid1()
    s = SmapInstance(ROOT_UUID)
    s.add_collection("/steve")
    t = Timeseries(s.uuid("sdh"), "V", buffersz=2)
    s.add_timeseries("/sensor0", t)
    s.set_metadata("/sensor0", {"Foo": "Bar", "Baz": 10})

    t.add(util.now(), 12)
    t.add(util.now(), 13)
    print s.get_timeseries(t['uuid'])
    print s.get_timeseries('/sensor0')
    print s.get_timeseries('/')

    #    s.get_collection('/').set_metadata({'Extra' : {"foo": " bar"}})
    print s.get_collection('/')

    #     print "Finding all Timeseries under /"
    print s._lookup_r('/', pred=ITimeseries.providedBy)
    print s.lookup('/+Timeseries')

    print s._lookup_r('/', pred=lambda x: x.dirty)

    # print s._lookup_r("/foo")
Example #9
0
File: server.py Project: ahaas/smap
        # easy-add -- create a timeseries automatically.  kwargs pass through
        # to the timeseries so you can change the data type, description, etc.
        #
        # the parent must exist and be a collection for this to work.
        #
        # arg0 : path to add at
        # arg1 : either a unique string (key) or a uuid instance
        # arg2 : units
        s.add_timeseries("/sensor0", "sdh", "V")

        # alternative -- add an existing timeseries
        s.add_timeseries("/sensor1", core.Timeseries(s.uuid("sdh2"), "F", buffersz=2))

        # add readings to a timeseries
        # get_timeseries will look up based on either path or uuid
        s.get_timeseries("/sensor0").add(util.now(), 12)
        s.get_timeseries("/sensor0").add(util.now(), 13)

        # you can set timeseries properties by accessing it as a dict.  The
        # changes you make must follow the smap schema and you will get a
        # SmapSchemaException if you try to write an invalid object.
        s.get_timeseries("/sensor0")['Metadata'] = \
            {'Instrument' : {
                'Manufacturer' : "Stephen Dawson-Haggerty"
                },
             'Extra' : {
                'Sucks' : 'Andrew'
                }
             }
        s.get_collection("/")["Metadata"] = {"Extra" : {"foo" : "bar"} }
Example #10
0
            self.s.send(cmd + "\r")
            reply = self.s.recv(1024)
            self.s.close()
            self.s = None
        except IOError, e:
            log.err()
            return
        else:
            if reply.startswith(cmd[1:]):
                val = float(reply[len(cmd) - 1:-1])
                # log.msg("read: " + str(val))
                if val == None:
                    time.sleep(0.5)
                    log.err("Failed to update reading")
                    return
            else:
                return
        this_time = util.now()

        # accumulate readings
        if self.last_time:
            self.accum += (self.last_time[1] + val) * (
                (this_time - self.last_time[0]) / 60.) * 0.5

        # and output a reading ever RATE seconds
        if this_time - self.last_add > self.rate:
            self.add('/0', this_time, float(val))
            self.add('/1', this_time, float(self.accum))
            self.last_add = this_time
        self.last_time = (this_time, val)
Example #11
0
    def _add(self, *args):
        """Add a new reading to this timeseries.  This version must
only be called from the :py:mod:`twisted` main loop; *i.e.* from a
callback added with ``reactor.callFromThread()``

Can be called with 1, 2, or 3 arguments.  The forms are

* ``_add(value)``
* ``_add(time, value)``
* ``_add(time, value, seqno)``

:raises SmapException: if the value's type does not match the stream
 type, or was called with an invalid number of arguments.
        """
        seqno = None
        if len(args) == 1:
            time = util.now()
            if self.milliseconds: time *= 1000
            value = args[0]
        elif len(args) == 2:
            time, value = args
        elif len(args) == 3:
            time, value, seqno = args
        else:
            raise SmapException("Invalid add arguments: must be (value), "
                                "(time, value), or (time, value, seqno)")

        # note that we got data now
        self.inst.statslog.mark()

        time = int(time)
        if not self.milliseconds:
            time *= 1000

        if not self._check_type(value):
            raise SmapException("Attempted to add " + str(value) + 
                                " to Timeseries, but " +
                                "the timeseries type is " + 
                                self.__getitem__('Properties')['ReadingType'])
        
        if seqno: reading = time, value, seqno
        else: reading = time, value
        self["Readings"].append(reading)
        if not hasattr(self, 'inst'): return

        # if a timeseries is dirty, we need to republish all of its
        # metadata before we publish it so stream is right. some of
        # this may have already been published, in which case it won't
        # actually do anything.
        if self.dirty:
            split_path = util.split_path(getattr(self, 'path'))
            for i in xrange(0, len(split_path)):
                path_seg = util.join_path(split_path[:i])
                self.inst.reports.publish(path_seg, 
                                          self.inst.get_collection(path_seg))
            rpt = dict(self)
            rpt['Readings'] = [reading]
            self.inst.reports.publish(getattr(self, 'path'), rpt)
            self.dirty = False
        else:
            # publish a stripped-down Timeseries object
            self.inst.reports.publish(getattr(self, 'path'),
                                      {'uuid' : self['uuid'],
                                       'Readings' : [reading]})
Example #12
0
    def unpause_reporting(self):
        return self.reports.unpause()

if __name__ == '__main__':
    ROOT_UUID = uuid.uuid1()
    s = SmapInstance(ROOT_UUID)
    s.add_collection("/steve")
    t = Timeseries(s.uuid("sdh"), "V", buffersz=2)
    s.add_timeseries("/sensor0", t)
    s.set_metadata("/sensor0", {
            "Foo" : "Bar",
            "Baz" : 10
            })

    t.add(util.now(), 12)
    t.add(util.now(), 13)
    print s.get_timeseries(t['uuid'])
    print s.get_timeseries('/sensor0')
    print s.get_timeseries('/')

#    s.get_collection('/').set_metadata({'Extra' : {"foo": " bar"}})
    print s.get_collection('/')


#     print "Finding all Timeseries under /"
    print s._lookup_r('/', pred=ITimeseries.providedBy)
    print s.lookup('/+Timeseries')

    print s._lookup_r('/', pred=lambda x: x.dirty)
Example #13
0
        # to the timeseries so you can change the data type, description, etc.
        #
        # the parent must exist and be a collection for this to work.
        #
        # arg0 : path to add at
        # arg1 : either a unique string (key) or a uuid instance
        # arg2 : units
        s.add_timeseries("/sensor0", "sdh", "V")

        # alternative -- add an existing timeseries
        s.add_timeseries("/sensor1",
                         core.Timeseries(s.uuid("sdh2"), "F", buffersz=2))

        # add readings to a timeseries
        # get_timeseries will look up based on either path or uuid
        s.get_timeseries("/sensor0").add(util.now(), 12)
        s.get_timeseries("/sensor0").add(util.now(), 13)

        # you can set timeseries properties by accessing it as a dict.  The
        # changes you make must follow the smap schema and you will get a
        # SmapSchemaException if you try to write an invalid object.
        s.get_timeseries("/sensor0")['Metadata'] = \
            {'Instrument' : {
                'Manufacturer' : "Stephen Dawson-Haggerty"
                },
             'Extra' : {
                'Sucks' : 'Andrew'
                }
             }
        s.get_collection("/")["Metadata"] = {"Extra": {"foo": "bar"}}
Example #14
0
        try:
            self.s.send(cmd + "\r")
            reply = self.s.recv(1024)
            self.s.close()
            self.s = None
        except IOError, e:
            log.err()
            return 
        else:
            if reply.startswith(cmd[1:]):
                val = float(reply[len(cmd) - 1:-1])
                # log.msg("read: " + str(val))
                if val == None:
                   time.sleep(0.5)
                   log.err("Failed to update reading")
                   return
            else:
                return
        this_time = util.now()

        # accumulate readings
        if self.last_time:
            self.accum += (self.last_time[1] + val) * ((this_time - self.last_time[0]) / 60.) * 0.5
            
        # and output a reading ever RATE seconds
        if this_time - self.last_add > self.rate:
            self.add('/0', this_time, float(val))
            self.add('/1', this_time, float(self.accum))
            self.last_add = this_time
        self.last_time = (this_time, val)