def _sendUpdatePatch(self, handler: Optional[PatchSink] = None): """ send a patch event out this handler to bring it up to date with self.statements """ now = time.time() selected = self.handlers if handler is not None: if handler not in self.handlers: log.error("called _sendUpdatePatch on a handler that's gone") return selected = {handler} # reduce loops here- prepare all patches at once for h in selected: period = .9 if 'Raspbian' in h.request.headers.get('user-agent', ''): period = 5 if h.lastPatchSentTime > now - period: continue p = self.statements.makeSyncPatch(h, set(self._sourcesForHandler(h))) log.debug('makeSyncPatch for %r: %r', h, p.jsonRepr) if not p.isNoop(): log.debug("send patch %s to %s", p.shortSummary(), h) # This can be a giant line, which was a problem # once. Might be nice for this service to try to break # it up into multiple sends, although there's no # guarantee at all since any single stmt could be any # length. h.sendEvent(message=jsonFromPatch(p).encode('utf8'), event=b'patch') h.lastPatchSentTime = now else: log.debug('nothing to send to %s', h)
def poll(self): ret = None startTime = time.time() try: url = (f'http://{deviceIp}/cgi-bin/cgi_manager').encode('ascii') resp = yield fetch( url, method=b'POST', headers={b'Authorization': [b'Basic %s' % auth]}, postdata=(f'''<LocalCommand> <Name>get_usage_data</Name> <MacId>0x{macId}</MacId> </LocalCommand> <LocalCommand> <Name>get_price_blocks</Name> <MacId>0x{macId}</MacId> </LocalCommand>''').encode('ascii'), timeout=10) ret = json.loads(resp.body) log.debug(ret) if ret['demand_units'] != 'kW': raise ValueError if ret['summation_units'] != 'kWh': raise ValueError pts = [ dict(measurement='housePowerW', fields=dict(value=float(ret['demand']) * 1000), tags=dict(house='berkeley'), time=int(startTime))] sd = float(ret['summation_delivered']) if sd > 0: # Sometimes nan pts.append(dict(measurement='housePowerSumDeliveredKwh', fields=dict(value=float()), tags=dict(house='berkeley'), time=int(startTime))) if 'price' in ret: pts.append(dict( measurement='price', fields=dict(price=float(ret['price']), price_units=float(ret['price_units'])), tags=dict(house='berkeley'), time=int(startTime), )) self.influx.write_points(pts, time_precision='s') self.graph.patchObject(context=ROOM['powerEagle'], subject=ROOM['housePower'], predicate=ROOM['instantDemandWatts'], newObject=Literal(float(ret['demand']) * 1000)) except Exception as e: traceback.print_exc() log.error("failed: %r", e) log.error(repr(ret)) os.abort() now = time.time() goal = startTime + periodSec - .2 reactor.callLater(max(1, goal - now), self.poll)
def poll(self): ret = None startTime = time.time() try: url = (f'http://{deviceIp}/cgi-bin/cgi_manager').encode('ascii') resp = yield fetch( url, method=b'POST', headers={b'Authorization': [b'Basic %s' % auth]}, postdata=(f'''<LocalCommand> <Name>get_usage_data</Name> <MacId>0x{macId}</MacId> </LocalCommand> <LocalCommand> <Name>get_price_blocks</Name> <MacId>0x{macId}</MacId> </LocalCommand>''').encode('ascii'), timeout=10) ret = json.loads(resp.body) log.debug(f"response body {ret}") if ret['demand_units'] != 'kW': raise ValueError if ret['summation_units'] != 'kWh': raise ValueError demandW = float(ret['demand']) * 1000 self.out['w'].set(demandW) sd = float(ret['summation_delivered']) if sd > 0: # Sometimes nan self.out['kwh'].set(sd) if 'price' in ret: self.out['price'].set(float(ret['price'])) self.graph.patchObject(context=ROOM['powerEagle'], subject=ROOM['housePower'], predicate=ROOM['instantDemandWatts'], newObject=Literal(demandW)) POLL_SUCCESSES.inc() except Exception as e: POLL_ERRORS.inc() traceback.print_exc() log.error("failed: %r", e) log.error(repr(ret)) now = time.time() goal = startTime + periodSec - .2 reactor.callLater(max(1, goal - now), self.poll)
def post(self): """ payload is an rdf graph. The statements are momentarily added to the input graph for exactly one update. todo: how do we go from a transition like doorclosed-to-open to a oneshot event? the upstream shouldn't have to do it. Do we make those oneshot events here? for every object change? there are probably special cases regarding startup time when everything appears to be a 'change'. """ try: log.info('POST to oneShot, headers=%s', self.request.headers) ct = self.request.headers.get( 'Content-Type', self.request.headers.get('content-type', '')) dt = self.settings.reasoning.inputGraph.addOneShotFromString( self.request.body, ct) self.set_header('x-graph-ms', str(1000 * dt)) except Exception as e: traceback.print_exc() log.error(e) raise
def poll(self): ms = get_idle_time() ctx = DEV['xidle/%s' % host] subj = URIRef("http://bigasterisk.com/host/%s/xidle" % host) lastMinActive = ms < 60 * 1000 now = int(time.time()) nextGraphUpdate = self.lastGraphSentTime + min(10, ms / 1000 / 2) if self.lastGraphSent != lastMinActive or now > nextGraphUpdate: masterGraph.patchObject(ctx, subj, ROOM['idleTimeMs'], Literal(ms)) masterGraph.patchObject(ctx, subj, ROOM['idleTimeMinutes'], Literal(round(ms / 1000 / 60, 2))) self.lastGraphSent = lastMinActive self.lastGraphSentTime = now if self.lastSent != lastMinActive or now > self.lastSentTime + 3600: self.points.append({ "measurement": "presence", "tags": { "host": host, "sensor": "xidle" }, "fields": { "value": 1 if lastMinActive else 0 }, "time": now }) self.lastSent = lastMinActive self.lastSentTime = now try: client.write_points(self.points, time_precision='s') except influxdb.exceptions.InfluxDBServerError as e: log.error(repr(e)) reactor.crash() self.points = []
def poll(self): try: newAddrs = yield self.wifi.getPresentMacAddrs() self.onNodes(newAddrs) except Exception as e: log.error("poll error: %r\n%s", e, traceback.format_exc())
this Usage: this [-v] [--cam host] [--port to_serve] Options: -v --verbose more log --port n http server [default: 10020] --cam host hostname of esphome server ''') verboseLogging(arguments['--verbose']) logging.getLogger('aioesphomeapi.connection').setLevel(logging.INFO) loop = asyncio.get_event_loop() recv = CameraReceiver(loop, arguments['--cam']) detector = apriltag.Detector() f = recv.start() loop.create_task(f) start_time = time.time() app = web.Application() app.router.add_route('GET', '/stream', stream) app.router.add_route('GET', '/', index) try: web.run_app(app, host='0.0.0.0', port=int(arguments['--port'])) except RuntimeError as e: log.error(e) log.info(f'run_app stopped after {time.time() - start_time} sec')