"""We subscribe to other sMAP sources, and they send us data. We just need to republish that to any interested parties. """ def __init__(self, inst): self.inst = inst resource.Resource.__init__(self) def getChild(self, name, request): if name == '': return self else: return SmapProxyEntity(self.inst, name) def getSite(inst): root = RootResource(value=['data', 'reports', 'proxy', 'publish']) pr = ProxyResource(inst) root.putChild('data', InstanceResource(inst)) root.putChild('proxy', pr) root.putChild('reports', ReportingResource(inst.reports)) root.putChild('publish', PublishResource(inst)) map(pr.update_proxy, PROXY_ORIGS) return server.Site(root) if __name__ == '__main__': log.startLogging(sys.stdout) inst = core.SmapInstance('d85eaa12-ac41-11e0-9f5f-0026bb56ec92') reactor.listenTCP(8081, getSite(inst)) reactor.run()
def setup(self, opts={}): self.t = self.add_timeseries('/sensor0', 'mytimeseries', 'SDH') self.set_metadata( '/sensor0', { 'Instrument/ModelName': 'ExampleInstrument', 'Extra/ModbusAddr': opts.get('ModbusAddr', '') }) self.counter = int(opts.get('StartVal', 0)) def start(self): self.counter = 0 util.periodicSequentialCall(self.read).start(1) def read(self): # print "Add", self.counter self.t.add(self.counter) self.counter += 1 # print self.counter if __name__ == '__main__': # inst = loader.load('default.ini', autoflush=False) # d = SmapDriverManager.get_driver('driver.BaseDriver', '/newsensor') # d.setup(inst) import uuid inst = core.SmapInstance(uuid.uuid1()) bd = SmapDriver.get_driver(inst, 'driver.BaseDriver', '/newsensor', None) bd.setup() server.run(inst)
"low", which are adjusted in parallel. """ def __init__(self, **kwargs): self.control_type = 'guardband' SmapActuator.__init__(self, **kwargs) if __name__ == '__main__': import uuid import server import json import sys from twisted.python import log from authentication import authenticated log.startLogging(sys.stdout) inst = core.SmapInstance('f80d0504-f2c6-11e0-80e6-ebc97648cfa4') class MyActuator(BinaryActuator): def setup(self, opts): self.state = 0 BinaryActuator.setup(self, opts) def get_state(self, request): print request print "getting" self.add(self.state) return self.state @authenticated(["__has_ssl__"]) def set_state(self, request, state):
if not os.path.exists(logdir): os.makedirs(logdir) print "Logging to", logdir print "Starting server on port", port # Allow 50 1MB files observer = log.FileLogObserver(LogFile('sMAP.log', logdir, rotateLength=1000000, maxRotatedFiles=50)) log.startLogging(observer) # Start server inst.start() reactor.listenTCP(port, getSite(inst)) reactor.run() if __name__ == '__main__': if len(sys.argv) == 2: # create a smap instance. each instance needs a uuid and it should s = core.SmapInstance('f83c98c0-a8c3-11e0-adf5-0026bb56ec92') # add collection -- easy # # arg0 : path to collection # arg1 : key to generate uuid with, or Collection instance s.add_collection("/steve") # 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
def load(file, sections=[], **instargs): """Create a sMAP instance based on the representation stored in a file. The configuration file contains sections which refer to either reporting instances, or paths in the sMAP heirarchy. Any section whose name starts with ``/`` is treated as a resource name; sections starting with ``report`` are treated as reports. The file must contain at least one section named ``/``, which must contain a ``uuid`` key to set the root identifier for the source. :param string file: filename of the configuration file :param instargs: arguments passed to the :py:class:`~smap.core.SmapInstance` constructor. :return smap.core.SmapInstance: the created instancev :raise smap.loader.SmapLoadError: an error is encountered processing the file :raise smap.core.SmapError: some other error is encountered validating the loaded object """ found = None for l in ['', os.getcwd(), sys.prefix]: path = os.path.join(l, file) if os.path.isfile(path): found = path if not found: raise Exception("Config file %s not found." % file) print "Loading config file:", found conf = configobj.ConfigObj(found, indent_type=' ') # if there's a server section, override the default server # configuration with that if 'server' in conf: smapconf.SERVER = util.dict_merge( smapconf.SERVER, dict(((k.lower(), v) for (k, v) in conf['server'].iteritems()))) # we need the root to have a uuid inst = core.SmapInstance(conf['/']['uuid'], **instargs) inst.loading = True reports = [] for s in conf: print "Loading section", s if s.startswith('report'): resource = conf[s].get('ReportResource', '/+') format = conf[s].get('Format', 'json') max_age = conf[s].get('MaxAge', None) max_age = int(max_age) if max_age != None else None dest = [conf[s]['ReportDeliveryLocation']] for i in xrange(0, 10): if 'ReportDeliveryLocation%i' % i in conf[s]: dest.append(conf[s]['ReportDeliveryLocation%i' % i]) reportinst = { 'ReportDeliveryLocation': dest, 'ReportResource': resource, 'Format': format, 'uuid': inst.uuid(s), 'MaxAge': max_age, } for o in ['MinPeriod', 'MaxPeriod']: if o in conf[s]: reportinst[o] = conf[s][o] for o in [ 'ClientCertificateFile', 'ClientPrivateKeyFile', 'CAFile' ]: if o in conf[s]: reportinst[i] = os.path.expanduser(conf[s][o]) reports.append(reportinst) continue elif not s.startswith('/'): # path sections must start with a '/' # other sections might be present and could be parsed by # other parts of the program print "Warning: skipping section", s, "since it does not begin with a '/'" continue elif len(sections) and not util.norm_path(s) in sections: # skip all but the listed sections if we were asked to continue s = util.norm_path(s) # build the UUID for the item props = util.build_recursive(dict(conf[s].items())) id = None if 'uuid' in conf[s]: key = None id = uuid.UUID(conf[s]['uuid']) elif 'key' in conf[s]: key = conf[s]['key'] else: # default to the path if key = s if key: id = inst.uuid(key) # raise SmapLoadError("Every config file section must have a uuid or a key!") # create the timeseries or collection if (s == '/' or conf[s].get("type", None) == 'Collection' or inst.get_collection(s) != None): if s == '/': c = inst.get_collection('/') elif inst.get_collection(s) != None: # sometimes you will have collections created twice, # for instance if a driver creates it and then we want # to tag it with metadata c = inst.get_collection(s) else: c = core.Collection(s, inst) inst.add_collection(s, c) elif conf[s].get("type", "Timeseries") == "Timeseries": if inst.get_timeseries(s) != None: c = inst.get_timeseries(s) else: try: props['Properties']['UnitofMeasure'] except KeyError: raise SmapLoadError("A Timeseries must have at least " "the Properites/UnitofMeasure key") # the Timeseries uses defaults if the conf file doesn't # contain the right sections. c = core.Timeseries( id, props['Properties']['UnitofMeasure'], data_type=props['Properties'].get( 'ReadingType', core.Timeseries.DEFAULTS['Properties/ReadingType']), timezone=props['Properties'].get( 'Timezone', core.Timeseries.DEFAULTS['Properties/Timezone']), buffersz=int( props.get('BufferSize', core.Timeseries.DEFAULTS['BufferSize']))) inst.add_timeseries(s, c) else: if not id: raise SmapLoadError( "A driver must have a key or uuid to generate a namespace") # load a new driver manager layer newdrv = driver.SmapDriver.get_driver(inst, conf[s]['type'], s, id) # create a collection and add it at the attachment point c = inst.get_collection(s) if not c: c = core.Collection(s, inst) inst.add_collection(s, c) # Add config file specified checkers for the driver check = checkers.get(inst, newdrv, conf[s]) if check: inst.checkers.append(check) # get the driver to add its points newdrv.setup(conf[s]) # Metadata and Description are shared between both Collections # and Timeseries if props.has_key('Metadata'): # the driver may have added metadata; however config file # metadata overrides it c['Metadata'] = util.dict_merge(c.get('Metadata', {}), props['Metadata']) if props.has_key('Description'): c['Description'] = props['Description'] if key: setattr(c, 'key', key) # since the sections could come in any order, update the reporting # instance to make sure all the topics are set right. for reportinst in reports: if not inst.reports.update_report(reportinst): inst.reports.add_report(reportinst) inst.reports.update_subscriptions() inst.loading = False return inst