[Python] help

C++, C#, Visual Basic, Delphi, Perl a ostatní

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod BigSandy 23. 3. 2016 11:24

Zdar tu všicí.

Snažim se o toto.
Arduino má teplotní čidla.
Naměřené hodnoty posilám po ser.portu
Serial.println("teplota_voda ,"+ teplota_voda)
Serial.println("teplota_kotel,"+ teplota_kotel);
teplota_voda ,51.9
teplota_kotel,62.8
Potřebují v python skript, který tuto komunikací bude zachytávat a zachycené hodnoty ukládat do souboru
Každé čidlo bude mit svůj soubor.
teplota_voda
teplota_kotel
Teploty se nebudou do souboru přidávat ale přepisovat, tedy bude v soubory vždy jen jedna hodnota.

Už jsem něco zkoušel.
Kód: Vybrat vše
#!/usr/bin/python
# -*- encoding: utf-8 -*-

import serial
import sys

ser = serial.Serial('/dev/ttyUSB0',9600)

while True:
   read_serial=ser.readline()
        #print read_serial 
     
        x = (read_serial[0:13] )

        if x == "teplota_kotel":
                 print "kotel"
                 y = (read_serial[14:] )
                 print(y)
                 soubor=file('/dev/shm/teplota_kotel','w')
                 soubor.write(y)
                 soubor.close()

        if x == "teplota_voda ":
                 print "voda"
                 y = (read_serial[14:] )
                 print(y)
                 soubor=file('/dev/shm/teplota_voda','w')
                 soubor.write(y)
                 soubor.close()



Problém 1
Fungovat to funguje.
Když však ukončím skript vyskočí toto.
Kód: Vybrat vše
^CTraceback (most recent call last):
  File "/home/pi/serialmonitor", line 10, in <module>
    read_serial=ser.readline()
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 446, in read
    ready,_,_ = select.select([self.fd],[],[], self._timeout)
KeyboardInterrupt



Problém 2
Když spadne komunikace po té ser. lince, skript se zhroutí a spadne.
Nějak se mi nedaří to nacpat do Try.
Pomuže někdo?
BigSandy
Junior

Odeslat příspěvekod JirkaVejrazka 23. 3. 2016 11:55

KeyboardInterrupt je spravne. Pokud ho nechces, dej udelej to takhle:
Kód: Vybrat vše
try:
    while True:
    ....
except KeyboardInterrupt:
    pass


A pokud koumunikace spadne, hodi to nejakou vyjimku, ne? (pyserial neznam, ale predpokladam, ze to bude nejaky potomek IOError. Tu muzes zachytavat *uvnitr* toho "while True" cyklu.

-- 23. 3. 2016 11:58 --

Mimochodem, ty zavorky v prirazovani "x" a "y" mas zbytecne, misto:
Kód: Vybrat vše
x = (read_serial[0:13] )

staci
Kód: Vybrat vše
x = read_serial[:13]


(da se vynechat i ta nula pri indexovani a bezne se to dela)

EDIT:
Mrknul jsem na to ( https://pythonhosted.org/pyserial/pyser ... exceptions ) a mel bys zachytavat serial.SerialException
JirkaVejrazka
Mírně pokročilý

Odeslat příspěvekod karlos00x 23. 3. 2016 13:16

python se tady tak jednou denne ukazuje :D
Upgrade který má smysl: SSD. Zažijete svižný počítač.
karlos00x
Pokročilý

Odeslat příspěvekod BigSandy 23. 3. 2016 13:30

:mrgreen: :mrgreen: Python.p Je to rebel!


No jo, ja už hledal řešení.
Všichni však dávají do try to ser = serial.Serial('/dev/ttyUSB0',9600)

Kód: Vybrat vše
while True:
        try:
            ser = serial.Serial('/dev/ttyUSB0',9600)
            #time.sleep(10)
            break

        except serial.SerialException:
            print 'Neni spojeni'
            time.sleep(3)


Což řeší připojení při spouštěni skriptu.

Pokud však spadne spojení třeba po hodině to nevyřeší.
try by mělo byt i v while True:

read_serial=ser.readline()
A to se nějak nedaří :hm
BigSandy
Junior

Odeslat příspěvekod JirkaVejrazka 23. 3. 2016 14:29

Co znamena "nedari"? Hodi to nejakou chybu, zastavi se to, ... ?
JirkaVejrazka
Mírně pokročilý

Odeslat příspěvekod BigSandy 23. 3. 2016 15:14

Pokus 1
Kód: Vybrat vše
#!/usr/bin/python
# -*- encoding: utf-8 -*-
import serial
import sys

while True:
            try:
                ser = serial.Serial('/dev/ttyUSB0',9600)
                #time.sleep(10)
                break

            except serial.SerialException:
                print 'Neni spojeni'
                time.sleep(3)

while True:
            try:
                read_serial = ser.readline()
                x = (read_serial[:13] )
                if x == "teplota_kotel":
                        print "kotel"
                        y = (read_serial[14:] )
                        print(y)
                        soubor=file('/dev/shm/teplota_kotel','w')
                        soubor.write(y)
                        soubor.close()

                if x == "teplota_voda ":
                         print "voda"
                         y = (read_serial[14:] )
                         print(y)
                         soubor=file('/dev/shm/teplota_voda','w')
                         soubor.write(y)
                         soubor.close()

            except:           
                ser.close()
                ser.open()
                continue


Pokus2
Kód: Vybrat vše
#!/usr/bin/python
# -*- encoding: utf-8 -*-

import serial
import sys

while True:
        try:
            ser = serial.Serial('/dev/ttyUSB0',9600)
            #time.sleep(10)
            break

        except serial.SerialException:
            print 'Neni spojeni'
            time.sleep(3)

while True:
         try:
           read_serial = ser.readline()
           x = (read_serial[:13] )
         except:           
           ser.close()
           ser.open()
           continue
               
         if x == "teplota_kotel":
                   print "kotel"
                   y = (read_serial[14:] )
                   print(y)
                   soubor=file('/dev/shm/teplota_kotel','w')
                   soubor.write(y)
                   soubor.close()

         if x == "teplota_voda ":
                   print "voda"
                   y = (read_serial[14:] )
                   print(y)
                   soubor=file('/dev/shm/teplota_voda','w')
                   soubor.write(y)
                   soubor.close()



U obou dvou se při přerušení spojení program zhroutí
Naposledy upravil BigSandy dne 23. 3. 2016 19:48, celkově upraveno 1
BigSandy
Junior

Odeslat příspěvekod JirkaVejrazka 23. 3. 2016 16:01

Zhrouti? Bez chyby? Nic nenapise?
JirkaVejrazka
Mírně pokročilý

Odeslat příspěvekod BigSandy 23. 3. 2016 17:11

Pokud se přeruší spojení tak u obou dvou
Kód: Vybrat vše
Traceback (most recent call last):
  File "/home/pi/serialmonitor1", line 23, in <module>
    ser.open()
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 278, in open
    raise SerialException("could not open port %s: %s" % (self._port, msg))
serial.serialutil.SerialException: could not open port /dev/ttyUSB0: [Errno 16] Device or resource busy: '/dev/ttyUSB0'
BigSandy
Junior

Odeslat příspěvekod JirkaVejrazka 23. 3. 2016 20:39

Pochopitelne, protoze se pokousis otevrit port v okamziku, kdy ma nejaky problem. Viz ser.open() v zachycovani vyjimky.

Jinak proste "exception" nikdy nepouzivej, tady ti staci zachycovat serial.SerialException. Pokud ti vyskoci, tak zavolej funkci, ktera se bude v cyklu pokouset ten port znovu otevrit a pokud to zrovna nepujde, tak se na nejakou dobu (treba 0.5 sekundy) uspi a pak to zkusi znovu. Obvykle se to jeste doplnuje pocitalem - kdyz se ten port nepovede otevrit treba po 100 pokusech, tak to ten program vzda uplne. Ale to je na tobe.
JirkaVejrazka
Mírně pokročilý

Odeslat příspěvekod BigSandy 23. 3. 2016 21:29

To jsem pochopil, že se to snaží znovu obnovit tu komunikací a proto tu vyhazuje to ser.open().
Bohužel, s python jsem začal dnes rano :-!

Kód: Vybrat vše
#!/usr/bin/python
# -*- encoding: utf-8 -*-

import serial
import sys
import time

def testspojeni():
         
            try:
               ser.close()
               ser.open()               
               
            except serial.SerialException:
               print 'Nefunguje spojení'
               


while True:
        try:
            ser = serial.Serial('/dev/ttyUSB0',9600)
            #time.sleep(10)
            break

        except serial.SerialException:
            print 'Neni spojeni'
            time.sleep(3)

while True:
         try:
           read_serial = ser.readline()
           x = (read_serial[:13] )
         except serial.SerialException:
           testspojeni()                   
           continue
               
         if x == "teplota_kotel":
                   print "kotel"
                   y = (read_serial[14:] )
                   print(y)
                   soubor=file('/dev/shm/teplota_kotel','w')
                   soubor.write(y)
                   soubor.close()

         if x == "teplota_voda ":
                   print "voda"
                   y = (read_serial[14:] )
                   print(y)
                   soubor=file('/dev/shm/teplota_voda','w')
                   soubor.write(y)
                   soubor.close()   


Kód: Vybrat vše
Nefunguje spojen▒
Traceback (most recent call last):
  File "/home/pi/serialmonitor1", line 29, in <module>
    read_serial = ser.readline()
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 443, in read
    if not self._isOpen: raise portNotOpenError
ValueError: Attempting to use a port that is not open


A to je max co mně tak napada 8-S
BigSandy
Junior

Odeslat příspěvekod JirkaVejrazka 24. 3. 2016 10:33

Ze jsi zacal s Pythonem rano nijak nevadi, zaklady Pythonu jsou jednoduche. Horsi je, ze nectes, co ti radim.

Pokud ti vyskoci, tak zavolej funkci, ktera se bude v cyklu pokouset ten port znovu otevrit a pokud to zrovna nepujde, tak se na nejakou dobu (treba 0.5 sekundy) uspi a pak to zkusi znovu.


Tvoje funkce testspojeni() je momentalne k nicemu - jenom jsi ten predchozi kod prepsal do funkce, ktera se pokousi *jednou* otevrit port, ktery je momentalne nepouzitelny.

Kdyz uz se ucis Python, tak jedno drobne vylepseni:
Kód: Vybrat vše
         if x == "teplota_kotel":
                   print "kotel"
                   y = (read_serial[14:] )
                   print(y)
                   soubor=file('/dev/shm/teplota_kotel','w')
                   soubor.write(y)
                   soubor.close()

         if x == "teplota_voda ":
                   print "voda"
                   y = (read_serial[14:] )
                   print(y)
                   soubor=file('/dev/shm/teplota_voda','w')
                   soubor.write(y)
                   soubor.close()   


Muzes to zkratit takto:
Kód: Vybrat vše
         if x in ["teplota_kotel", "teplota_voda"]:
                   y = (read_serial[14:] )
                   print(x, y)
                   with open('/dev/shm/%s' % x,'w') as soubor:
                       soubor.write(y)

JirkaVejrazka
Mírně pokročilý

Odeslat příspěvekod BigSandy 24. 3. 2016 11:31

Vyřešeno.
Dik všem co pomohli a poradili.
BigSandy
Junior

Odeslat příspěvekod BigSandy 4. 4. 2016 10:18

Pokračovaní.
Mame tada v souboru teplota_kotel uloženou teplotu třeba 28.4
Potřebují s toho souboru krmit rrdtool.

Kód: Vybrat vše
soubor=file('/dev/shm/teplota_kotel','r')
teplota1 = soubor.read()
soubor.close()
float(teplota1)
print(teplota1)
from rrdtool import update as rrd_update
ret = rrd_update('/home/pi/databaze_teplota.rrd', 'N:%s:%s' %(teplota1, teplota1));


14.3
Traceback (most recent call last):
File "/home/pi/test", line 11, in <module>
ret = rrd_update('/home/pi/databaze_teplota.rrd', 'N:%s:%s' %(teplota1, teplota1));
rrdtool.error: /home/pi/databaze_teplota.rrd: conversion of '14.3
' to float not complete: tail '
BigSandy
Junior

Odeslat příspěvekod JirkaVejrazka 4. 4. 2016 10:25

Pokud neco prectes ze souboru (zvlast, pokud ctes cely soubor vcelku pomoci read()) je vhodne pat na tech datech udelat .strip(), tj. "teplota1.strip()". Tim se zbavis prebytecnych mezer a znaku konce radku (\n), ktere tam pravdepodobne jsou a ktere float() nema rad.

Predpokladam ze vis, ze radek "float(teplota1)" v tehle podobe nic nevraci?
JirkaVejrazka
Mírně pokročilý

Odeslat příspěvekod BigSandy 4. 4. 2016 10:33

Kód: Vybrat vše
ret = rrd_update('/home/pi/databaze_teplota.rrd', 'N:%s:%s' %(teplota1.strip(), teplota1.strip()));

;-)
Ja myslel že float(teplota1) mi převede řetězec na float :hm

Dik moc.
BigSandy
Junior

Další stránka

Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků