Python: Update Sensor Data to Variable - python

I have a temperature and pressure gauge that I want to use to track the temperature over time with. Since I may end up with multiple sensors over time, I want to be able to reference my BMP085 sensor as tp. In other words, I would like to call tp.temp or tp.pressure to obtain the current temperature, etc. The problem is that tp.temp or .pressure is not updating each time I call it. Suggestions?
#!/usr/bin/env python
#temperature logger for the BMP085 Temperature and Pressure Sensor on the Raspberry Pi
from Adafruit_BMP085 import BMP085
from time import sleep
import pickle, sys, os
class tps():
def __init__(self):
#temperature/pressure sensor setup
self.bmp = BMP085(0x77)
self.temp = self.bmp.readTemperature()*1.8+32
self.pressure = self.bmp.readPressure()*0.0002953
class data():
def __init__(self):
self.tp = tps()
self.savedata()
def savedata(self):
# if os.path.exists("data.dat")==True:
# if os.path.isfile("data.dat")==True:
# fileHandle = open ( 'data.dat' )
# olddata = pickle.load ( fileHandle )
# fileHandle.close()
print self.tp.temp, self.tp.pressure
sleep(4)
print self.tp.temp, self.tp.pressure
# newdata = [self.tp.temp, self.tp.pressure]
# self.datadump = [olddata]
# self.datadump.append(newdata)
# fileHandle = open ( 'data.dat', 'w' )
# pickle.dump ( self.datadump, fileHandle )
# fileHandle.close()
data()

That's because you only called the bmp.readTemperature() and bmp.readPressure() functions once - in tps.__init__. In your print statements at the end, you're just twice reading the values that those functions returned, rather than getting updated values.
Here's an example of how to get updated values:
class tps():
def __init__(self):
#temperature/pressure sensor setup
self.bmp = BMP085(0x77)
self.temp = None
self.pressure = None
# If you want to initialize your tps object with sensor data, you can call your updater method here.
self.updateTempAndPressure()
# Here's a function that you can call whenever you want updated data from the sensor
def updateTempAndPressure(self):
self.temp = self.bmp.readTemperature()*1.8+32
self.pressure = self.bmp.readPressure()*0.0002953
class data():
def __init__(self):
self.tp = tps()
self.savedata()
def savedata(self):
# Call the method that gets updated data from the sensor
self.tp.updateTempAndPressure()
print self.tp.temp, self.tp.pressure
sleep(4)
# Call the update method again
self.tp.updateTempAndPressure()
print self.tp.temp, self.tp.pressure
data()

Related

Python class keeps giving me the same value

Hi im new to Python and im trying to figure out python classes.
I have made the following script, and I don't understand when I make the object vejr, outside the while loop, it keeps printing the same value over and over again.
If i make the object inside the while loop it works and print the temperature as it changes.
Inside the loop I make a new vejr object every time the loop runs, I thought it would be enough just make the vejr object once?? or is there a better way to write code like this?
import requests
import json
from datetime import datetime
import time
class Owm_data():
def __init__(self, api_key="api_key", lat="51.507351", lon="-0.127758" ):
self.api_key = api_key
self.lat = lat
self.lon = lon
self.url = "https://api.openweathermap.org/data/2.5/onecall?lat=%s&lon=%s&appid=%s&units=metric" % (lat, lon, api_key)
self.response = requests.get(self.url)
self.data = json.loads(self.response.text)
def get_temperature(self):
return self.data["current"]["temp"]
def get_pressure(self):
return self.data["current"]["pressure"]
vejr = Owm_data()
while True:
print(vejr.get_temperature())
time.sleep(30)
I recommend distinguishing between temperature as an attribute versus a method. For instance:
class Owm_data():
def __init__(self, api_key="api_key", lat="51.507351", lon="-0.127758" ):
self.api_key = api_key
self.lat = lat
self.lon = lon
self.temperature = self.get_temperature()
def get_temperature(self):
self.url = "https://api.openweathermap.org/data/2.5/onecall?lat=%s&lon=%s&appid=%s&units=metric" % (lat, lon, api_key)
self.response = requests.get(self.url)
self.data = json.loads(self.response.text)
self.temperature = self.data["current"]["temp"]
return self.temperature
This way, if you want to access the cached value of the temperature, you can do print(vejr.temperature). If you want to update the value of the temperature, you can do print(vejr.get_temperature()). Although you might want to use a name that makes it clear that the temperature is being updated, such as update_temperature().
You pull the data when you initialize the class, and you only do that outside the loop. So your vejr.get_temperature() call is just reproducing the same cached information you saw at construction. If you want to recheck the data each loop, change from:
vejr = Owm_data()
while True:
print(vejr.get_temperature())
time.sleep(30)
to:
while True:
vejr = Owm_data()
print(vejr.get_temperature())
time.sleep(30)
so the class is reconstructed on each loop and repulls the data.
Other solutions might include pulling the data each call to get_temperature and friends, rather than doing it in the initializer, but leaving the design as is is more useful when you want cached data so you can see both temperature and pressure from a single moment of time with one call.

class function Callback is not accessed

No error when I start the script and but the callback of the class startSacnRec doesn't work and Visual Code give me the info "Callback is not accessed"
class sacnRec():
#contstruktur super().__init__(self) Elternklasse vererbung aufrufen
def __init__(self, fileName, universum):
self.fileName = fileName
self.universum = universum
def deleteFile(self):
with open(self.fileName + '.txt','w'): pass
def packettoIntData(data):
uniData = str(data)[1:-1]
uniDataList = [int(s) for s in uniData.split(',')]
return uniDataList
def writeCsv(set,data,fileName):
with open(fileName + '.txt', "a") as file:
file.write(str(set))
file.write(str(data))
def startSacnRec(self):
print("Start des Servers" + str(self.universum))
receiver = sacn.sACNreceiver()
receiver.start()
#receiver.listen_on('universe', universe=self.universum) # listens on universe 1
def callback(packet): # packet type: sacn.DataPacket
print(packet.dmxData)
print(packet.sourceName)
print("test")
#uniOneSet = [int(packet.universe),int(packet.priority),str(packet.sourceName) ]
#print(uniOneSet)
# uniOneDmx = packettoIntData(packet.dmxData)
#writeCsv(uniOneSet,uniOneDmx, name)
receiver.join_multicast(1)
time.sleep(10) # receive for 10 seconds
receiver.stop()
one = sacnRec(1,1)
one.startSacnRec()
I think the problem is here
enter image description here
Using a decorator (the #receiver.listen_on... part) is usually for class methods.
If you want to use a closure based callback, then use receiver.register_listener approach.
https://github.com/Hundemeier/sacn#receiving-1

access a class instance/variable from one running python file in another?

I have a problem that involves collecting data continuously from multiple sources.
My setup as it is currently, writes each data entry from each source to a MySQL db, and then, with another python program, does Select's that bring all the data together. I need to make INSERT's at roughly 1000/second and as it is my SELECT's can take 15-20 seconds each.
The whole process takes so long the data is obsolete before I get to do anything useful with it.
I have created a toy example to try and demonstrate what I am looking for.
program 1 'generateClasses':
import time
import random
from datetime import datetime
class Race:
def __init__(self,name):
hist = {}
now = datetime.now()
self.name = name
self.now = now
hist[now] = 0
self.v = 0
self.hist = hist # example variable's.
def update(self,name,v):
now = datetime.now()
hist = self.hist
hist[now] = v
self.v = v
self.now - now
self.hist = hist
class Looper:
def __init__(self,name):
self.a = Race(name)
def loop(self,name):
# simulating the streaming API
while True:
v = self.a.v
v += 1
self.a.update(name,v)
print(a,datetime.now(),v) # can i access this stream using the location displayed with the print(a)?
time.sleep(0.1) # this should be more like time.sleep(0.001)
def pickData(self,name):
v = self.v
self.loop(name)
print('The state at {} {} = '.format(self.now,self.v))
return self.hist
if __name__ == "__main__":
x = 'Some_ID'
a = Looper(x)
a.loop(x)
program 2:
from generateClasses import Looper
from datetime import datetime
import time
start_time = int((datetime.now() - datetime(1970, 1, 1)).total_seconds())
print(start_time)
x = 'Some_orher_ID'
a = Looper(x)
print('this will print')
a.loop(x)
print('this wont ever print')
a.pickdata(x)
# this last section is the functionality i am looking for in this program, but, as it is, it will never run.
x = ‘Some_ID’
while True:
now_time = int((datetime.now() - datetime(1970, 1, 1)).total_seconds())
print(start_time)
if int(now_time-start_time) == 10:
a.pickData(x)
# b.pickData(x)
# c.pickData(x)
# d.pickData(x)
# make further actions.....
What happens currently in my examples is that it creates its own loop using the class structure from the first program.
What I want it to do is call the the pickData() method from program 2 at timely intervals of my choosing on a loop running in another program.
Is my best option picking a db located in memory and getting a faster computer?
Maybe something can be done with the object location shown when you print the instance name?
I have uploaded to github if anybody fancies it..
I would be grateful of any suggestions.
also, recommendations for further reading would be appreciated also.

Python UNO on LibreOffice Calc, rehoming a cursor

LibreOffice 5.3, python 3.53, VOID Linux
This is more of an uno question than a python question. The code below does a simple update of 3 cells. 3 buttons configured on the sheet calling dowriteonce() dowritetwice() and dowritethrice(), and they all update and work like you might expect writing numbers and text to selected cells.
Where the problem comes in, is that when a cell is edited in the UI by a user, any subsequent update of that cell by means of executing the function is blocked. So simply clicking cell C4 in the calc UI, prevents the writethrice() function from updating cell C4. If I delete the content and click another cell in the UI, say C5, then everything works normally again and C4 updates when the button is clicked.
What I would like to do is relocate the UI edit-cursor to an unused cell prior to execution in order to prevent this. User copy-paste is going to leave the active cursor in unpredictable places and that will bork calculations if I can't isolate the cursor.
So the question is, how do I move the UI edit cursor to a named cell via the UNO API, with Python? Or if it is easier, just deactivate it temporarily.
Python:
import socket
import sys
import re
import uno
import unohelper
class ODSCursor(unohelper.Base):
# predeclare class properties
ctx=None
desktop=None
model=None
activesheet=None
counter=0
scooby="Scooby"
# import namespaces
def __init__(self):
import socket
import uno
import unohelper
import sys
import re
# initialize uno handle only once and get the first sheet
#classmethod
def sheet1(cls,*args):
if cls.activesheet is not None:
return (cls.activesheet)
cls.ctx = uno.getComponentContext()
cls.desktop = cls.ctx.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", cls.ctx)
cls.model = cls.desktop.getCurrentComponent()
# cls.activesheet = cls.model.Sheets.getByName("Sheet1")
cls.activesheet = cls.model.Sheets.getByIndex(0)
return (cls.activesheet)
#classmethod
def writeonce(self,*args):
self.counter += 1
cell_b1 = self.activesheet.getCellRangeByName("B1")
cell_b1.String = self.counter
#classmethod
def writetwice(self,*args):
self.counter += 1
cell_b2 = self.activesheet.getCellRangeByName("B2")
cell_b2.String = self.counter
#classmethod
def writescooby(self,*args):
cell_c4 = self.activesheet.getCellRangeByName("C4")
cell_c4.String = self.scooby
### BUTTON BOUND FUNCTIONS ###
def dowriteonce(*args):
Odc = ODSCursor() # create the object
Odc.sheet1()
Odc.writeonce()
def dowritetwice(*args):
Odc = ODSCursor() # create the object
Odc.sheet1()
Odc.writetwice()
def dowritethrice(*args):
Odc = ODSCursor() # create the object
Odc.sheet1()
Odc.writescooby()
In the following code, cells are deselected before changing the values, then selected again. This way, cells can be modified even when left in edit mode by the user.
There also seems to be some confusion about Python class methods and variables, so I changed those parts as well.
import uno
import unohelper
SCOOBY = "Scooby"
class ODSCursor(unohelper.Base):
def __init__(self):
self.ctx = None
self.desktop = None
self.document = None
self.controller = None
self.sheet = None
self.counter = 0
def sheet1(self):
"""Initialize uno handle only once and get the first sheet."""
if self.sheet is not None:
return self.sheet
self.ctx = uno.getComponentContext()
self.desktop = self.ctx.ServiceManager.createInstanceWithContext(
"com.sun.star.frame.Desktop", self.ctx)
self.document = self.desktop.getCurrentComponent()
self.controller = self.document.getCurrentController()
self.sheet = self.controller.getActiveSheet()
return self.sheet
def writeonce(self):
self.writeval("B1", self.inc())
def writetwice(self):
self.writeval("B2", self.inc())
def writescooby(self):
self.writeval("C4", SCOOBY)
def writeval(self, address, value):
self.deselect()
cell = self.sheet.getCellRangeByName(address)
cell.String = value
self.controller.select(cell)
def deselect(self):
"""Select cell A1, then select nothing."""
cell_a1 = self.sheet.getCellByPosition(0, 0)
self.controller.select(cell_a1)
emptyRanges = self.document.createInstance(
"com.sun.star.sheet.SheetCellRanges")
self.controller.select(emptyRanges)
def inc(self):
"""Increment the counter and return the value."""
self.counter += 1
return self.counter
odsc = ODSCursor()
### BUTTON BOUND FUNCTIONS ###
def dowriteonce(dummy_oEvent):
odsc.sheet1()
odsc.writeonce()
def dowritetwice(dummy_oEvent):
odsc.sheet1()
odsc.writetwice()
def dowritethrice(dummy_oEvent):
odsc.sheet1()
odsc.writescooby()

Moving variables from one Qthread to another with pyqtsignal

I am building my first GUI in pyQT5 and I am pretty new to Python programming.
I am trying to use a set a Variable in one Qthread and using it in another. I figured that pyqtsignal was the way to do it. But i can't get it to work.
class GetCurrentSpeed(QThread):
gpsLatSig = pyqtSignal(str)
def __init__(self):
QThread.__init__(self)
def __del__(self):
self.wait()
def run(self):
while True:
####Print a value in lon and lat so that its never empty
lon = "18"
lat = "59"
###Get Current Latitude and Longitude
if report['class'] == 'TPV':
if hasattr(report, 'lat'):
lat = (str(report.lat))
self.gpsLatSig.emit(lat)
else:
lat = "59"
print("No GPS Lock")
self.gpsLatSig.emit(lat)
class PosSignals(QObject):
GetGps = GetCurrentSpeed()
def connectsig(self):
self.GetGps.gpsLatSig[str].connect(self.handle_string)
#pyqtSlot(str)
def handle_string(self, text):
print text
class OverPassApi(QThread):
GetGps = GetCurrentSpeed()
def __init__(self):
QThread.__init__(self)
self.b = PosSignals()
def __del__(self):
self.wait()
def run(self):
while True:
self.b.connectsig()
print b.handle_string()
api = overpy.Overpass()
result = api.query("""<osm-script>
<query type="way">
<around lat="%s" lon="%s" radius="30"/>
<has-kv k="name" v=""/>
</query>
<print/>
</osm-script>""" % (b.handle_string, 18))
This is just a part of the program and this might contain other errors since i have worked hard to get this to work.
My Issue is that I get the output "<main.PosSignals object at 0x72f0c210>" when i try to print the text in the handle function when i remove self like:
#pyqtSlot(str)
def handle_string(text):
print text
and when I keep self I need to provide an argument to the print b.handle_string() which then ofcourse only prints the argument I add.
What I want to achieve is to use the lat variable created in GetCurrentSpeed(QThread): and use it in class OverPassApi(QThread):
Looks like you simply forgot a self argument for handle_string.

Categories