def parseBitStream(bits, elevation=0.0, inputDataDict=None, verbose=False): """ Given a sequence of bits from readRTL/readRTLFile, find all of the valid Oregon Scientific v2.1 packets and return the data contained within the packets as a dictionary. In the process, compute various derived quantities (dew point, windchill, and sea level corrected pressure). .. note:: The sea level corrected pressure is only compute if the elevation (in meters) is set to a non-zero value. """ # Setup the output dictionary output = {} if inputDataDict is not None: for key, value in inputDataDict.iteritems(): output[key] = value # Find the packets and save the output i = 0 while i < len(bits) - 32: ## Check for a valid preamble (and its logical negation counterpart) if sum(bits[i:i + 32:2]) == 16 and sum(bits[i + 1:i + 1 + 32:2]) == 0: ### Assume nothing valid = False ### Packet #1 packet = bits[i + 0::2] try: valid, sensorName, channel, sensorData = parsePacketv21( packet, verbose=verbose) except IndexError: pass if not valid: ### Packet #2 packet = bits[i + 1::2] try: valid, sensorName, channel, sensorData = parsePacketv21( packet, verbose=verbose) except IndexError: pass ### Data reorganization and computed quantities if valid: #### Dew point - indoor and output if sensorName in ('BHTR968', 'THGR268', 'THGR968'): sensorData['dewpoint'] = computeDewPoint( sensorData['temperature'], sensorData['humidity']) #### Sea level corrected barometric pressure if sensorName in ('BHTR968', ) and elevation != 0.0: sensorData['pressure'] = computeSeaLevelPressure( sensorData['pressure'], elevation) #### Disentangle the indoor temperatures from the outdoor temperatures if sensorName == 'BHTR968': for key in ('temperature', 'humidity', 'dewpoint'): newKey = 'indoor%s' % key.capitalize() sensorData[newKey] = sensorData[key] del sensorData[key] #### Multiplex the THGR268 values for key in sensorData.keys(): if key in ('temperature', 'humidity', 'dewpoint'): if sensorName == 'THGR968': output[key] = sensorData[key] else: try: output['alt%s' % key.capitalize()][channel - 1] = sensorData[key] except KeyError: output['alt%s' % key.capitalize()] = [ None, None, None, None ] output['alt%s' % key.capitalize()][channel - 1] = sensorData[key] else: output[key] = sensorData[key] i += 1 # Compute combined quantities if 'temperature' in output.keys() and 'average' in output.keys(): output['windchill'] = computeWindchill(output['temperature'], output['average']) # Done return output
def parsePacketStream(packets, elevation=0.0, inputDataDict=None): """ Given a sequence of two-element type,payload packets from read433, find all of the Oregon Scientific sensor values and return the data as a dictionary. In the process, compute various derived quantities (dew point, windchill, and sea level correctedpressure). .. note:: The sea level corrected pressure is only compute if the elevation (in meters) is set to a non-zero value. """ # Setup the output dictionary output = {} if inputDataDict is not None: for key,value in inputDataDict.iteritems(): output[key] = value # Parse the packet payload and save the output gspd = [] gdir = [] for pType,pPayload in packets: if pType == 'OSV2': valid, sensorName, channel, sensorData = parsePacketv21(pPayload) else: continue ## Data reorganization and computed quantities if valid: ### Gust tracker if sensorName == 'WGR968': gspd.append( sensorData['gust'] ) gdir.append( sensorData['direction'] ) ### Dew point - indoor and output if sensorName in ('BHTR968', 'THGR268', 'THGR968'): sensorData['dewpoint'] = computeDewPoint(sensorData['temperature'], sensorData['humidity']) ### Sea level corrected barometric pressure if sensorName in ('BHTR968',) and elevation != 0.0: sensorData['pressure'] = computeSeaLevelPressure(sensorData['pressure'], elevation) ### Disentangle the indoor temperatures from the outdoor temperatures if sensorName == 'BHTR968': for key in ('temperature', 'humidity', 'dewpoint'): newKey = 'indoor%s' % key.capitalize() sensorData[newKey] = sensorData[key] del sensorData[key] ### Multiplex the THGR268 values for key in sensorData.keys(): if key in ('temperature', 'humidity', 'dewpoint'): if sensorName == 'THGR968': output[key] = sensorData[key] else: try: output['alt%s' % key.capitalize()][channel-1] = sensorData[key] except KeyError: output['alt%s' % key.capitalize()] = [None, None, None, None] output['alt%s' % key.capitalize()][channel-1] = sensorData[key] else: output[key] = sensorData[key] # Compute combined quantities ## Maximum gust observed if len(gspd) > 0: best = gspd.index( max(gspd) ) output['gust'] = gspd[best] output['gustDirection'] = gdir[best] ## Windchill if 'temperature' in output.keys() and 'average' in output.keys(): output['windchill'] = computeWindchill(output['temperature'], output['average']) # Done return output
def run(self): tLastUpdate = 0.0 sensorData = self.sensorData while self.alive.isSet(): ## Begin the loop t0 = time.time() ## Load in the current configuration wuID = self.config.get('Account', 'id') wuPW = self.config.get('Account', 'password') radioPin = self.config.getint('Station', 'radiopin') duration = self.config.getfloat('Station', 'duration') elevation = self.config.getfloat('Station', 'elevation') enableBMP085 = self.config.getbool('Station', 'enablebmp085') includeIndoor = self.config.getbool('Station', 'includeindoor') ## Read from the 433 MHz radio for i in xrange(self.loopsForState): self.leds['red'].on() tData = time.time() + int(round(duration - 5)) / 2.0 packets = read433(radioPin, int(round(duration - 5))) self.leds['red'].off() ## Process the received packets and update the internal state self.leds['yellow'].on() sensorData = parsePacketStream(packets, elevation=elevation, inputDataDict=sensorData) self.leds['yellow'].off() # Poll the BMP085/180 - if needed if enableBMP085: self.leds['red'].on() ps = BMP085(address=0x77, mode=3) pressure = ps.readPressure() / 100.0 temperature = ps.readTemperature() self.leds['red'].off() self.leds['yellow'].on() sensorData['pressure'] = pressure sensorData['pressure'] = computeSeaLevelPressure( sensorData['pressure'], elevation) if 'indoorHumidity' in sensorData.keys(): sensorData['indoorTemperature'] = ps.readTemperature() sensorData['indoorDewpoint'] = computeDewPoint( sensorData['indoorTemperature'], sensorData['indoorHumidity']) self.leds['yellow'].off() ## Have we built up the state? if self.buildState: self.loopsForState = 1 ## Check if there is anything to update in the archive self.leds['yellow'].on() if tData != tLastUpdate: self.db.writeData(tData, sensorData) pollLogger.info('Saving current state to archive') else: pollLogger.warning( 'Data timestamp has not changed since last poll, archiving skipped' ) self.leds['yellow'].off() ## Post the results to WUnderground if tData != tLastUpdate: uploadStatus = wuUploader(wuID, wuPW, tData, sensorData, archive=self.db, includeIndoor=includeIndoor) if uploadStatus: tLastUpdate = 1.0 * tData pollLogger.info('Posted data to WUnderground') self.leds['green'].blink() time.sleep(3) self.leds['green'].blink() else: pollLogger.error('Failed to post data to WUnderground') self.leds['red'].blink() time.sleep(3) self.leds['red'].blink() else: pollLogger.warning( 'Data timestamp has not changed since last poll, archiving skipped' ) ## Done t1 = time.time() tSleep = duration - (t1 - t0) tSleep = tSleep if tSleep > 0 else 0 ## Sleep time.sleep(tSleep)
def parseBitStream(bits, elevation=0.0, inputDataDict=None, verbose=False): """ Given a sequence of bits from readRTL/readRTLFile, find all of the valid Oregon Scientific v2.1 packets and return the data contained within the packets as a dictionary. In the process, compute various derived quantities (dew point, windchill, and sea level corrected pressure). .. note:: The sea level corrected pressure is only compute if the elevation (in meters) is set to a non-zero value. """ # Setup the output dictionary output = {} if inputDataDict is not None: for key,value in inputDataDict.iteritems(): output[key] = value # Find the packets and save the output i = 0 while i < len(bits)-32: ## Check for a valid preamble (and its logical negation counterpart) if sum(bits[i:i+32:2]) == 16 and sum(bits[i+1:i+1+32:2]) == 0: ### Assume nothing valid = False ### Packet #1 packet = bits[i+0::2] try: valid, sensorName, channel, sensorData = parsePacketv21(packet, verbose=verbose) except IndexError: pass if not valid: ### Packet #2 packet = bits[i+1::2] try: valid, sensorName, channel, sensorData = parsePacketv21(packet, verbose=verbose) except IndexError: pass ### Data reorganization and computed quantities if valid: #### Dew point - indoor and output if sensorName in ('BTHGN129', 'THGN800', 'THGN800'): sensorData['dewpoint'] = computeDewPoint(sensorData['temperature'], sensorData['humidity']) #### Disentangle the indoor temperatures from the outdoor temperatures if sensorName == 'BTHGN129': for key in ('temperature', 'humidity', 'dewpoint','pressure'): output[key] = sensorData[key] #### Multiplex the THGN800 values for key in sensorData.keys(): if key in ('temperature', 'humidity', 'dewpoint'): if sensorName == 'THGN800': output[key] = sensorData[key] else: try: output['alt%s' % key.capitalize()][channel-1] = sensorData[key] except KeyError: output['alt%s' % key.capitalize()] = [None, None, None, None] output['alt%s' % key.capitalize()][channel-1] = sensorData[key] else: output[key] = sensorData[key] i += 1 # Compute combined quantities if 'temperature' in output.keys() and 'average' in output.keys(): output['windchill'] = computeWindchill(output['temperature'], output['average']) # Done return output
def run(self): tLastUpdate = 0.0 sensorData = self.sensorData while self.alive.isSet(): ## Begin the loop t0 = time.time() ## Load in the current configuration wuID = self.config.get('Account', 'id') wuPW = self.config.get('Account', 'password') radioPin = self.config.getint('Station', 'radiopin') duration = self.config.getfloat('Station', 'duration') elevation = self.config.getfloat('Station', 'elevation') enableBMP085 = self.config.getbool('Station', 'enablebmp085') includeIndoor = self.config.getbool('Station', 'includeindoor') ## Read from the 433 MHz radio for i in xrange(self.loopsForState): self.leds['red'].on() tData = time.time() + int(round(duration-5))/2.0 packets = read433(radioPin, int(round(duration-5))) self.leds['red'].off() ## Process the received packets and update the internal state self.leds['yellow'].on() sensorData = parsePacketStream(packets, elevation=elevation, inputDataDict=sensorData) self.leds['yellow'].off() # Poll the BMP085/180 - if needed if enableBMP085: self.leds['red'].on() ps = BMP085(address=0x77, mode=3) pressure = ps.readPressure() / 100.0 temperature = ps.readTemperature() self.leds['red'].off() self.leds['yellow'].on() sensorData['pressure'] = pressure sensorData['pressure'] = computeSeaLevelPressure(sensorData['pressure'], elevation) if 'indoorHumidity' in sensorData.keys(): sensorData['indoorTemperature'] = ps.readTemperature() sensorData['indoorDewpoint'] = computeDewPoint(sensorData['indoorTemperature'], sensorData['indoorHumidity']) self.leds['yellow'].off() ## Have we built up the state? if self.buildState: self.loopsForState = 1 ## Check if there is anything to update in the archive self.leds['yellow'].on() if tData != tLastUpdate: self.db.writeData(tData, sensorData) pollLogger.info('Saving current state to archive') else: pollLogger.warning('Data timestamp has not changed since last poll, archiving skipped') self.leds['yellow'].off() ## Post the results to WUnderground if tData != tLastUpdate: uploadStatus = wuUploader(wuID, wuPW, tData, sensorData, archive=self.db, includeIndoor=includeIndoor) if uploadStatus: tLastUpdate = 1.0*tData pollLogger.info('Posted data to WUnderground') self.leds['green'].blink() time.sleep(3) self.leds['green'].blink() else: pollLogger.error('Failed to post data to WUnderground') self.leds['red'].blink() time.sleep(3) self.leds['red'].blink() else: pollLogger.warning('Data timestamp has not changed since last poll, archiving skipped') ## Done t1 = time.time() tSleep = duration - (t1-t0) tSleep = tSleep if tSleep > 0 else 0 ## Sleep time.sleep(tSleep)
def parsePacketStream(packets, elevation=0.0, inputDataDict=None): """ Given a sequence of two-element type,payload packets from read433, find all of the Oregon Scientific sensor values and return the data as a dictionary. In the process, compute various derived quantities (dew point, windchill, and sea level correctedpressure). .. note:: The sea level corrected pressure is only compute if the elevation (in meters) is set to a non-zero value. """ # Setup the output dictionary output = {} if inputDataDict is not None: for key,value in inputDataDict.iteritems(): output[key] = value # Parse the packet payload and save the output gspd = [] gdir = [] for pType,pPayload in packets: if pType == 'OSV2': valid, sensorName, channel, sensorData = parsePacketv21(pPayload) else: continue ## Data reorganization and computed quantities if valid: ### Gust tracker if sensorName == 'WGR968': gspd.append( sensorData['gust'] ) gdir.append( sensorData['direction'] ) ### Dew point - indoor and output if sensorName in ('BHTR968', 'THGR268', 'THGR968'): sensorData['dewpoint'] = computeDewPoint(sensorData['temperature'], sensorData['humidity']) ### Sea level corrected barometric pressure if sensorName in ('BHTR968',) and elevation != 0.0: sensorData['pressure'] = computeSeaLevelPressure(sensorData['pressure'], elevation) ### Disentangle the indoor temperatures from the outdoor temperatures if sensorName == 'BHTR968': for key in ('temperature', 'humidity', 'dewpoint'): newKey = 'indoor%s' % key.capitalize() sensorData[newKey] = sensorData[key] del sensorData[key] ### Multiplex the THGR268 values for key in sensorData.keys(): if key in ('temperature', 'humidity', 'dewpoint'): if sensorName == 'THGR968': output[key] = sensorData[key] else: try: output['alt%s' % key.capitalize()][channel-1] = sensorData[key] except KeyError: output['alt%s' % key.capitalize()] = [None, None, None, None] output['alt%s' % key.capitalize()][channel-1] = sensorData[key] else: output[key] = sensorData[key] # Compute combined quantities ## Maximum gust observed if len(gspd) > 0: best = gspd.index( max(gspd) ) output['gust'] = gspd[best] output['gustDirection'] = gdir[best] ## Windchill if 'temperature' in output.keys() and 'average' in output.keys(): output['windchill'] = computeWindchill(output['temperature'], output['average']) # Done return output