Начать новую тему 
Ответить на тему 
Сообщение
СообщениеДобавлено: 28.03.17 19:25
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 08.01.2015
Сообщения: 48
Минимальный демон написан: начну с версии 2.0. Задействовано: БП ATX, камера, свет, вентиляция, температура. Пока демон ещё не опробован в услових реального выращивания.

Придумал условия алгоритма климат-контроля:
-при включении демона делается фото, если свет выключен - включается на время создания фото;
-есть четыре параметра температуры:
--минимальная = 16 град. - ниже этого предела вентилляция всегда выключается
--максимальная = 32 град. - выше этого предела всегда выключается освещение
--нормальная минимальная = 26 град. если меньше - понемногу уменьшается вентилляция.
--нормальная максимальная = 28 град. если больше - понемногу увеличивается вентилляция.
-прстой между периодами просчитывания автоматики = 1 минута.
-освещение... естественно по графику 18/6

Проведу ещё несколько тестов, а потом выложу код. :rasta:


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 29.03.17 00:01
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 04.06.2015
Сообщения: 2187
Поздравляю с положеным началом! :friend:

Цитата:
-при включении демона делается фото, если свет выключен - включается на время создания фото/quote]
Цитата:
--максимальная = 32 град. - выше этого предела всегда выключается освещение

Вот эти условия по факту к реальному грову не очень применимы имхо - лучше 33-35 градусов на несколько часов, чем мигающий свет. То же самое про включение света при съемки фото.
А зачем делать фото при включении демона? Просто задаешь условие, например, каждую первую минуту часа снимать фото, если релеха освещения включена.

_________________
Клубника / 142Вт LED / минвата / капля / соли


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 18.04.17 23:54
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 08.01.2015
Сообщения: 48
Цитата:
А зачем делать фото при включении демона? Просто задаешь условие, например, каждую первую минуту часа снимать фото, если релеха освещения включена.

Свет что-то часто отключали, хотел чтобы снимало при включении электричества, надо над этим ещё подумать.

Демон (сервис) 2.0
Тестить в реальных (садовых) условиях сейчас нет возможности (холодно). Выкладываю "как есть".
Код для каждого устройства разместил в отдельных файлах в виде классов - демон во время работы всех их подключает. Но также почти каждый файл можно использовать как самостоятельную программу, которую можно запускать отдельно.
Резместил демон в папке /tumbox/svc
354232
Снимки складываются в папке /tumbox/svc/photo
Также у классов есть некоторая защита от многопоточного достуа.
Принцип работы
Сервис через автозагрузку включается при старте Оранжа. Сервис работает в два потока: один следит за климатом, второй через TCP/IP обрабатывает клиентские запросы (команды).
atx.py - блок питания ATX
Код:
#!/usr/bin/env python

import threading
from pyA20.gpio import gpio
from pyA20.gpio import port

class Atx:
        LOCK = threading.RLock()

        Port = port.PA7
        Current = False

        def __init__(self):
                gpio.setcfg(self.Port, gpio.OUTPUT)

        def Set(self, NewValue):
                OutLevel = gpio.LOW
                if NewValue:
                        OutLevel = gpio.HIGH

                self.LOCK.acquire()
                gpio.output(self.Port, OutLevel)
                self.Current = NewValue
                self.LOCK.release()

        def Get(self):
                self.LOCK.acquire()
                self.Current = gpio.input(self.Port)
                Cur =  self.Current
                self.LOCK.release()
                return Cur

        def On(self):
                self.Set(True)

        def Off(self):
                self.Set(False)

if __name__ == "__main__":
        import sys
        gpio.init()
        atx = Atx()
        if len(sys.argv) >= 2:
                StringCommand = sys.argv[1]
                if StringCommand == "on":
                        atx.On()
                        print("ATX set on")
                elif StringCommand == "off":
                        atx.Off()
                        print("ATX set off")
                else:
                        print("Unknown command: %s", StringCommand)
        else:
                if atx.Get():
                        print("ATX is on")
                else:
                        print("ATX is off")


При самомтоятельном выволнении:
без команы - показывает текущее сотояние включённости БП "on" или "off"
с командой "on" или "off" - включает/выключает ATX.
По такому принципу действуют и другие файлы устройтв.

light.py - управление светом
Код:
#!/usr/bin/env python

import datetime, threading
from pyA20.gpio import gpio
from pyA20.gpio import port

class Light:
        LOCK = threading.RLock()
        LOCK_Update = threading.RLock()

        Port = port.PC4
        Current = None
        TemperatureObject = None

        OnHour = 5
        LightHours = 18
        Automode = "off" #on, off, auto

        def __init__(self, TemperatureObject = None):
                self.TemperatureObject = TemperatureObject
                gpio.setcfg(self.Port, gpio.OUTPUT)

        def Set(self, NewValue):
                self.LOCK.acquire()
                OutLevel = gpio.LOW
                if NewValue:
                        OutLevel = gpio.HIGH
                gpio.output(self.Port, OutLevel)
                self.Current = NewValue
                self.LOCK.release()

        def Get(self):
                self.LOCK.acquire()
                self.Current = gpio.input(self.Port)
                Cur = self.Current
                self.LOCK.release()
                return Cur

        def On(self):
                self.Set(True)

        def Off(self):
                self.Set(False)

        def Update(self):
                self.LOCK_Update.acquire()

                if self.Automode == "on":
                        self.On()
                elif self.Automode == "off":
                        self.Off()
                elif self.Automode == "auto":
                        # hard regulation
                        CurrentTem = self.TemperatureObject.GetCurrent()
                        if CurrentTem != None:
                                if CurrentTem.Temperature > self.TemperatureObject.GetMaxTem():
                                        self.Off()
                                        self.LOCK_Update.release()
                                        return

                        # check hours
                        if self.LightHours >= 24 or self.OnHour >= 24:
                                self.On()
                        else:
                                OffHour = self.OnHour + self.LightHours
                                now = datetime.datetime.now()
                                if OffHour >= 24:
                                        OffHour -= 24

                                        # specific set light
                                        if now.hour >= self.OnHour or now.hour < OffHour:
                                                self.On()
                                        else:
                                                self.Off()
                                else:
                                        # set light
 if now.hour >= self.OnHour and now.hour < OffHour:
                                                self.On()
                                        else:
                                                self.Off()
                self.LOCK_Update.release()
                return self.GetCurrent()

        def GetCurrent(self):
                self.LOCK.acquire()
                Cur = self.Current
                self.LOCK.release()
                return Cur

        def GetAutomode(self):
                self.LOCK_Update.acquire()
                Cur = self.Automode
                self.LOCK_Update.release()
                return Cur

        def SetAutomode(self, NewMode):
                self.LOCK_Update.acquire()
                self.Automode = NewMode
                self.LOCK_Update.release()
if __name__ == "__main__":
        import sys
        gpio.init()
        light = Light()
        if len(sys.argv) >= 2:
                StringCommand = sys.argv[1]
                if StringCommand == "on":
                        light.On()
                        print("Light set on")
                elif StringCommand == "off":
                        light.Off()
                        print("Light set off")
                else:
                        print("Unknown command: %s", StringCommand)
        else:
                if light.Get():
                        print("Light is on")
                else:
                        print("Light is off")

Настройки:
OnHour - о котором часу включать свет
LightHours - количество часов работы
Возможна недоделка: OnHour + LightHours не должно привышать число 24.

tem.py - датчик температуры и влажности DHT11
Код:
!/usr/bin/env python
# v.1.2017.5.6

from pyA20.gpio import gpio
from pyA20.gpio import port
import sys, time, datetime, threading
sys.path.append("/tumbox/DHT11_Python")
import dht11

class TemResult:
        Temperature = 0
        Humidity = 0

class Tem:
        LOCK = threading.RLock()
        Port = port.PA1
        Instance = None
        Current = None
        LastNiceCurrent = None
        LastNiceCurrentTime = None
        AsDaemon = False

        # Check parameters
        Skip = 1
        Take = 3
        TryCount = 10
        Pause = 2

        # Source for automation
        MinTem = 16
        MaxTem = 32
        NormalMinTem = 26
        NormalMaxTem = 28

        def __init__(self, AsDaemon):
                self.AsDaemon = AsDaemon
                self.Instance = dht11.DHT11(pin = self.Port)

        def Read(self):
                self.Update()

                self.LOCK.acquire()
                Cur = self.Current
                self.LOCK.release()
                return Cur

        def GetLastNiceCurrent(self):
                self.LOCK.acquire()
                Cur = self.LastNiceCurrent
                self.LOCK.release()
                return Cur
        def GetLastNiceCurrentTime(self):
                self.LOCK.acquire()
                Cur = self.LastNiceCurrentTime
                self.LOCK.release()
                return Cur
        def Update(self):
                self.LOCK.acquire()
                self.Current = None
                CurrentTryCount = 0

                # skip
                Count = 0
                while (Count < self.Skip) and (CurrentTryCount <= self.TryCount):
                        result = self.Instance.read()
                        if result.is_valid():
                                Count +=1
                                if self.AsDaemon == False:
                                        print("Tem.Update():skip:OK %d C" % result.temperature)
                        else:
                                if self.AsDaemon == False:
                                        print("Tem.Update():skip:ERROR")
                        CurrentTryCount += 1
                        time.sleep(self.Pause)
                if CurrentTryCount > self.TryCount:
                        self.LOCK.release()
                        return

                # take
                Count = 0
                ResultsTem = []
                ResultsHum = []
                while (Count < self.Take) and (CurrentTryCount <= self.TryCount):
                        result = self.Instance.read()
                        if result.is_valid():
                                Count +=1
                                ResultsTem.append(result.temperature)
                                ResultsHum.append(result.humidity)
                                if self.AsDaemon == False:
                                        print("Tem.Update():take:OK %d C" % result.temperature)
                        else:
                                if self.AsDaemon == False:
                                        print("Tem.Update():take:ERROR")
                        CurrentTryCount += 1
                        time.sleep(self.Pause)
                if CurrentTryCount > self.TryCount and len(ResultsTem)==0:
                        self.LOCK.release()
                        return

                # calculate results
                Result = TemResult()

                for OneTem in ResultsTem:
                        Result.Temperature += OneTem
                Result.Temperature /= len(ResultsTem)

                for OneTem in ResultsHum:
                        Result.Humidity += OneTem
                Result.Humidity /= len(ResultsHum)

                self.Current = Result

                # nice result
                self.LastNiceCurrent = Result
                self.LastNiceCurrentTime = datetime.datetime.now()
                self.LOCK.release()

        def GetMinTem(self):
                self.LOCK.acquire()
                Cur = self.MinTem
                self.LOCK.release()
                return Cur

        def GetMaxTem(self):
                self.LOCK.acquire()
                Cur = self.MaxTem
                self.LOCK.release()
                return Cur
        def GetNormalMinTem(self):
                self.LOCK.acquire()
                Cur = self.NormalMinTem
                self.LOCK.release()
                return Cur

        def GetNormalMaxTem(self):
                self.LOCK.acquire()
                Cur = self.NormalMaxTem
                self.LOCK.release()
                return Cur

        def GetCurrent(self):
                self.LOCK.acquire()
                Cur = self.Current
                self.LOCK.release()
                return Cur

if __name__ == "__main__":
        gpio.init()
        tem = Tem(False)
        result = tem.Instance.read()
        if result.is_valid():
                print("Temperature: %d C" % result.temperature)
                print("Humidity: %d %%" % result.humidity)
        else:
                print("Read ERROR")


Настройки получения замера:
Skip = 1 - сколько первых замеров пропускать, первый замер может оставаться из предыдущего раза
Take = 3 - сколько успешных замеров должно быть получено для успешного результата
TryCount = 10 - количество попыток получения замеров, 10 - производиться максимум десять замеров, если успешных будет 4 (1 + 3) - значит общий замер удался.
Pause = 2 - пауза в секундах между попытками получения замеров.

Настройки для автоматизации:
MinTem - минимально допустимая температура, текущая меньше её - значит пипец - выключение вентилляции.
MaxTem - максимально допустимая температура, текущая больше её - опять пипец - выключение освещения.
NormalMinTem/NormalMaxTem - диапазон температур считающихся нормальным (удерживается оборотами вентиляции).

vent.py - вентиляция
Код:
#!/usr/bin/env python
# v1.2017.5.6

import threading
from pyA20.gpio import gpio
from pyA20.gpio import port
import tem

class Vent:
        LOCK = threading.RLock()
        LOCK_Update = threading.RLock()
        #LOCK_GetMinMaxSpeed = threading.RLock()

        WentPort1 = port.PG8
        WentPort2 = port.PG9
        WentPort3 = port.PG6
        WentPort4 = port.PG7

        CurrentSpeed = 0
        MinSpeed = 5
        MaxSpeed = 15

        TemperatureObject = None
        Automode = "manual" #manual, auto

        def __init__(self, TemperatureObject = None):
                self.TemperatureObject = TemperatureObject

                gpio.setcfg(self.WentPort1, gpio.OUTPUT)
                gpio.setcfg(self.WentPort2, gpio.OUTPUT)
                gpio.setcfg(self.WentPort3, gpio.OUTPUT)
                gpio.setcfg(self.WentPort4, gpio.OUTPUT)

        def SetSpeed(self, NewSpeed):
                self.LOCK.acquire()
                if NewSpeed != 0 and (NewSpeed < self.MinSpeed or NewSpeed > self.MaxSpeed):
                        self.LOCK.release()
                        return False

                self.CurrentSpeed = NewSpeed

                # WentPort1
                if self.CurrentSpeed & 1 == 1:
                        gpio.output(self.WentPort1, gpio.HIGH)
                else:
                        gpio.output(self.WentPort1, gpio.LOW)

                # WentPort2
                if self.CurrentSpeed & 2 == 2:
                        gpio.output(self.WentPort2, gpio.HIGH)
                else:
                        gpio.output(self.WentPort2, gpio.LOW)

                # WentPort3
                if self.CurrentSpeed & 4 == 4:
                        gpio.output(self.WentPort3, gpio.HIGH)
                else:
                        gpio.output(self.WentPort3, gpio.LOW)

                # WentPort4
                if self.CurrentSpeed & 8 == 8:
                        gpio.output(self.WentPort4, gpio.HIGH)
                else:
                        gpio.output(self.WentPort4, gpio.LOW)
                self.LOCK.release()
                return True

        def GetSpeed(self):
                self.LOCK.acquire()
                self.CurrentSpeed = 0
                if gpio.input(self.WentPort1):
                        self.CurrentSpeed += 1
                if gpio.input(self.WentPort2):
                        self.CurrentSpeed += 2
                if gpio.input(self.WentPort3):
                        self.CurrentSpeed += 4
                if gpio.input(self.WentPort4):
                        self.CurrentSpeed += 8
                Cur = self.CurrentSpeed
                self.LOCK.release()
                return Cur
        def Update(self):
                self.LOCK_Update.acquire()
                if self.Automode == "auto":
                        CurrentTem = self.TemperatureObject.GetCurrent()
                        if CurrentTem != None:
                                NewSpeed = self.GetSpeed()

                                # hard regulation
                                if CurrentTem.Temperature < self.TemperatureObject.GetMinTem():
                                        NewSpeed = 0
                                else:
                                        # delicat regulation
                                        if CurrentTem.Temperature < self.TemperatureObject.GetNormalMinTem():
                                                if NewSpeed > self.MinSpeed:
                                                        NewSpeed -= 1
                                        elif CurrentTem.Temperature > self.TemperatureObject.GetNormalMaxTem():
                                                 if NewSpeed < self.MaxSpeed:
                                                        NewSpeed += 1
                                if NewSpeed == 1:
                                        NewSpeed = self.MinSpeed
                                self.SetSpeed(NewSpeed)
                self.LOCK_Update.release()

        def GetAutomode(self):
                self.LOCK_Update.acquire()
                Cur = self.Automode
                self.LOCK_Update.release()
                return Cur

        def SetAutomode(self, NewMode):
                self.LOCK_Update.acquire()
                self.Automode = NewMode
                self.LOCK_Update.release()

        def GetMinSpeed(self):
                self.LOCK_Update.acquire()
                Cur = self.MinSpeed
                self.LOCK_Update.release()
                return Cur

        def GetMaxSpeed(self):
                self.LOCK_Update.acquire()
                Cur = self.MaxSpeed
                self.LOCK_Update.release()
                return Cur

if __name__ == "__main__":
        import sys
        gpio.init()
        vent = Vent()
        if len(sys.argv) >= 2:
                NewSpeed = int(sys.argv[1])
                print("Vent set speed - %r" % vent.SetSpeed(NewSpeed))
        else:
                print("Vent speed: %d" % vent.GetSpeed())

Настройки:
MinSpeed = 5 - минимальная скорость, меньше этой скорости мои кулера не крутиться
MaxSpeed = 15 - максимальная скорость, больше просто нельзя задать аппаратно.

cam.py - камера, создание снимков
Код:
#!/usr/bin/env python

import subprocess, datetime, time, os, glob

class Cam:
        LightObject = None

        CameraDevice = None
        MakePhotoCommand = "ffmpeg -t 1 -f video4linux2 -s 640x480 -r 10 -i %s -f image2 %swebcam1_%%05d.png"
        PhotoDirectory = "/tumbox/svc/photo/"
        PhotoTempDirectory = "/tumbox/svc/photo/temp/"

        def __init__(self, LightObject = None, CameraDevice = "/dev/video0"):
                self.LightObject = LightObject
                self.CameraDevice = CameraDevice

        def Shot(self, LightAutoOn = False):
                # if camera device not exists
                if os.path.isfile(self.CameraDevice) == False:
                        return False

                # check now time
                now = datetime.datetime.now()

                # auto on light
                AutoOn = False
                if self.LightObject != None and LightAutoOn and self.LightObject.Get() == False:
                        AutoOn = True
                        self.LightObject.On()
                        time.sleep(2)   #delay for power on

                # making temp shots
                if os.path.isdir(self.PhotoTempDirectory) == False:
                        os.makedirs(self.PhotoTempDirectory)
                ShellCommand = self.MakePhotoCommand % (self.PhotoTempDirectory, self.CameraDevice)
                subprocess.call(ShellCommand, shell=True)

                # check exists photo directory
                CurrentPhotoDirectory = self.PhotoDirectory + now.strftime("%Y/%m/")
                if os.path.isdir(CurrentPhotoDirectory) == False:
                        os.makedirs(CurrentPhotoDirectory)

                # check target file if exists
                TargetFile = CurrentPhotoDirectory + "shot_%s.png" % now.strftime("%d_%H-%M-%S")
                while os.path.isfile(TargetFile) == True:
                        now = datetime.datetime.now()
                        TargetFile = CurrentPhotoDirectory + "shot_%s.png" % now.strftime("%d_%H-%M-%S")

                # copy last shot to photo directory
                SourceFile = self.PhotoTempDirectory + "webcam1_00010.png"
                if os.path.isfile(SourceFile) == True:
                        ShellCommand = "mv %s %s" % (SourceFile, TargetFile)
                        subprocess.call(ShellCommand, shell=True)

                        # delete temp shots
                        for file in glob.glob(self.PhotoTempDirectory + "*"):
                                os.remove(file)
                else:
                        TargetFile = False

                # auto off light
                if AutoOn:
                        self.LightObject.Off()
                return TargetFile


if __name__ == "__main__":
        cam = Cam()
        print("New shot: " + cam.Shot())

PhotoDirectory - куда складывать файлы фото, автоматом создаются подпапки года и месяца
PhotoTempDirectory - сюда делается серия снимков одного раза, и изымается только последнее фото для PhotoDirectory, остальные удаляются

svc.py - главный файл демона
Код:
#!/usr/bin/python
# Tumbox daemon v2.2017.5.6

# standart import
import os, sys, socket, time, threading

# daemonize
AsDaemon = False
if "daemon" in sys.argv:
        pid = os.fork()
        if pid > 0:
                # parent process
                print ("Daemon started")
                sys.exit()
        elif pid == 0:
                # daemon (child)
                AsDaemon = True

#Hight priority
os.nice(-20)

#gpio import
from pyA20.gpio import gpio
from pyA20.gpio import port

# my import
import tem, atx, light, vent, cam

# initialize objects
gpio.init()
Temperature = tem.Tem(AsDaemon)
Atx = atx.Atx()
Atx.On()        # allways atx on
Light = light.Light(Temperature)
Vent = vent.Vent(Temperature)
Cam = cam.Cam(Light)
Cam.Shot(True)  # allways making shot on start daemon
AcceptingSocket = True

# enable automation for all
if "noauto" not in sys.argv:
        Light.SetAutomode("auto")
        Vent.SetAutomode("auto")

# initialize cross-thread objects
LockHalting = threading.RLock()
Halting = False

# worker thread
def worker():
        global Temperature
        global Light
        global Vent
        global Halting

        while True:
                Temperature.Update()
                Light.Update()
                Vent.Update()
                time.sleep(1*60)

                # halting
                LockHalting.acquire()
                if Halting:
                        if AsDaemon == False:
                                print("need to stop")
                        LockHalting.release()
                        break
                else:
                        if AsDaemon == False:
                                print("non stop")
                LockHalting.release()

# processing lines
def processing_line(line):
        global Temperature
        global Light
        global Vent
        global Halting
        global AcceptingSocket
        global Cam

        if line == "info":
                InfoString = ""

                # Tem
                AdditionalString = "[%d..%d] (%d..%d) " % (Temperature.GetNormalMinTem(), Temperature.GetNormalMaxTem(), Temperature.GetMinTem(), Temperatur$
                AdditionalString += Temperature.GetLastNiceCurrentTime().strftime("%H:%M:%S %Y-%m-%d")
                ReadedTem = Temperature.GetLastNiceCurrent()
                if(ReadedTem == None):
                        InfoString += "Temperature: none %s\nHumidity: none\n" % AdditionalString
                else:
                        InfoString += "Temperature: %d C %s\n" % (ReadedTem.Temperature, AdditionalString)
                        InfoString += "Humidity: %d %%\n" % ReadedTem.Humidity

                # ATX
                InfoString += "ATX: "
                if Atx.Get():
                        InfoString += "on"
                else:
                        InfoString += "off"
                InfoString += "\n"

                # Light
                InfoString += "Light: "
                InfoString += "Light: "
                if Light.Get():
                        InfoString += "on"
                else:
                        InfoString += "off"
                InfoString += " (%s)" % Light.GetAutomode()
                InfoString += "\n"

                # Vent
                InfoString += "Vent: %d (%s) [0, %s..%s]\n" % (Vent.GetSpeed(), Vent.GetAutomode(), Vent.GetMinSpeed(), Vent.GetMaxSpeed())

                return InfoString

        elif line == "halt":
                LockHalting.acquire()
                Halting = True
                LockHalting.release()
                AcceptingSocket = False
                return "Stopping daemon..."

        elif line == "light on":
                Light.SetAutomode("on")
                Light.Update()
                return "ok"

        elif line == "light off":
                Light.SetAutomode("off")
        elif line == "light auto":
                Light.SetAutomode("auto")
                Light.Update()
                return "ok"

        elif line == "vent manual":
                Vent.SetAutomode("manual")
                Vent.Update()
                return "ok"

        elif line == "vent auto":
                Vent.SetAutomode("auto")
                Vent.Update()
                return "ok"

        elif line.find("vent ") == 0:
                NewSpeed = line[5:]
                try:
                        NewSpeed = int(NewSpeed)
                except Exception:
                        return "incorrect speed"
                if Vent.SetSpeed(NewSpeed):
                        Vent.Update()
                        return "ok"
                else:
                        return "cancel"
        elif  line == "cam shot":
                return "New shot: " +  Cam.Shot(True)

        return "error line: %s" % line

# -main-

# starting check thread
CheckThread = threading.Thread(target=worker)
CheckThread.start()

# setup socket server
sock = socket.socket()
sock.bind(('127.0.0.1', 9191))
sock.listen(1)

#waiting for connection
while AcceptingSocket:
        conn, addr = sock.accept()
        if AsDaemon == False:
                print("Accept client: ", addr)

        string_line = ""
        string_buffer = ""

        # reading
        reading = True
        while AcceptingSocket and reading:
                data = conn.recv(1024)

                # end connecion
                if not data:
                        if AsDaemon == False:
                                print("End connection: ", addr)
                        break

                # parsing one string line
                string_buffer += data
                try:
                        n_index = string_buffer.index('\n')
                except ValueError:
                        n_index = -1
                while n_index >=0:
                        string_line = string_buffer[0:n_index]
                        n_index +=1
                        string_buffer = string_buffer[n_index:]
                        try:
                                n_index = string_buffer.index('\n')
                        except ValueError:
                        n_index = -1
                while n_index >=0:
                        string_line = string_buffer[0:n_index]
                        n_index +=1
                        string_buffer = string_buffer[n_index:]
                        try:
                                n_index = string_buffer.index('\n')
                        except ValueError:
                                n_index = -1
                        answer = processing_line(string_line)

                        # sending answer
                        try:
                                conn.send(answer)
                        except socket.error:
                                conn.close()
                                n_index = -1
                                reading = False
                                if AsDaemon == False:
                                        print("Client closed: ", addr)

sock.close()

В автозагрузке он должен запускаться с параметром "daemon", чтобы после запуска "отпустить" командную строку.
Параметр "noauto", отключает переход демона в автоматический (рабочий) режим управления.
Если запустить без параметра он будет "держать" командную строку занатой всё время работы - это удобно для отладки - показываются некоторые процессы работы.

client.py - клиент демона
Код:
import sys, socket

SkipConnecting = False

# check command
StringCommand = 'info'
if len(sys.argv) >= 2:
        StringCommand = sys.argv[1]
        if StringCommand == "help":
                print("|Command|                |Description|")
                print("help                     show this help info")
                print("info                     show all current info")
                print("halt                     shutdown daemon")
                print("light on/off/auto        set mode for light")
                print("vent manual/auto        set mode for ventilation")
                print("vent <speed: 0, 5..15>  set speed for ventilation")
                print("cam shot         make shot from camera now")
                sys.exit()
        else:
                StringCommand = ' '.join(sys.argv[1:])

else:
        print("Default command: " + StringCommand)

# connecting
sock = socket.socket()
sock.connect(('127.0.0.1', 9191))

# send command
StringCommand += '\n'
sock.send(StringCommand)

data = sock.recv(1024)
print(data)
sock.close()


через запуск этой программы можно управлять запущенным демоном, смотреть текущее состояние.
Запуск с параметром help показывает все доступные команды с описанием.
Запуск без параметров - отображение текущей информации (режим работы и значения всех устройств).
354233
Для автозагрузки демона в файл /tumbox/autostart.sh я добавил строку:
Код:
/tumbox/svc/svc.py daemon noauto

noauto - потомучто ничего сейчас не растёт
Жду тепла :sun:


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 14.05.17 16:29
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 08.01.2015
Сообщения: 48
DHT11 с оранжом хреново работает, бывает и по пол дня не может получить температуру. Это сводит все усилия на нет. Наверное надо его как-то через PIC-контроллер сделать.


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 14.05.17 18:11
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 04.06.2015
Сообщения: 2187
аКустик, DHT вообще так себе работают) 22й чуть получше. У меня в одной итерации считывания инфы - 5 опросов DHT22 - стабильно 1 из 5 невалидный и еще часто выдает в 2 раза большие значения. Я сделал логическую валидацию и все статистически выбивающиеся значения отбрасываю.

_________________
Клубника / 142Вт LED / минвата / капля / соли


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 28.05.17 00:27
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 05.01.2011
Сообщения: 224
Что я только-что прочитал :spin:

_________________
Organic garden коло хати, and bees між шишками гудуть...


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 18.11.17 16:04
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 13.11.2009
Сообщения: 159
аКустик, ты с нами? :spy:

_________________
И, пожалуйста, помните: мы - не юристы, правила - не УК, наказания раздают не святые. :facepalm:


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 05.12.17 22:15
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One

Регистрация: 20.01.2006
Сообщения: 6592
Ну как дела? Работает ебанина?

_________________
-- In Code We Trust --


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 07.01.18 15:09
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 08.01.2015
Сообщения: 48
Вобщем ничего не вышло.
Посадил одну растиху, ударила жара и бедняжка скончалась (в гровинге дилетант). Если на улице 35, два кулера ниже этой температуры не охладят никогда, надо использовать элементы Пельтье.
Факт роста энергопотребления скрыть от домашних не удалось - это и поставило крест на проекте. Надо было начинать с солнечных батарей и аккумулятора.
Куча программного кода на форуме только путает людей, это наверно надо сайт заводить с обновлениями программы.
Сейчас Оранж интернет раздаёт :) Может будет какой-нибудь "умный дом":)


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 07.01.18 15:45
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 13.11.2009
Сообщения: 159
аКустик [07.01.18 15:09] писал(а):
Вобщем ничего не вышло.
Посадил одну растиху, ударила жара и бедняжка скончалась (в гровинге дилетант). Если на улице 35, два кулера ниже этой температуры не охладят никогда, надо использовать элементы Пельтье.
Факт роста энергопотребления скрыть от домашних не удалось - это и поставило крест на проекте. Надо было начинать с солнечных батарей и аккумулятора.
Куча программного кода на форуме только путает людей, это наверно надо сайт заводить с обновлениями программы.
Сейчас Оранж интернет раздаёт :) Может будет какой-нибудь "умный дом":)


В нашем деле главное на свободе оставаться! :smile: Скажу тебе так, тут не с солнечных панелей начинать надо, а с помещения о котором никто не знает.

_________________
И, пожалуйста, помните: мы - не юристы, правила - не УК, наказания раздают не святые. :facepalm:


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
СообщениеДобавлено: 07.01.18 16:28
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 17.02.2015
Сообщения: 148
Всегда жаль, когда такие здравые идеи не могут развиваться из-за отсутствия условий.

_________________
ice cold killer


 Профиль Найти сообщения пользователя  
Ответить с цитатой
СообщениеДобавлено: 07.01.18 17:03
Заголовок сообщения: Re: Тумбокс 2: тумбочка + Orange PI One
Аватара пользователя

Регистрация: 30.03.2016
Сообщения: 1459
аКустик, Скажи майнингом домашним занялся :notice:
А так по факту жаль бро что старания так кончились... :friend: :facepalm:

_________________
Дело сделанное не вовремя, становится проблемой


 Профиль Найти сообщения пользователя Галерея  
Ответить с цитатой
Показать сообщения за:  Сортировать по  

Начать новую тему 
Ответить на тему 
 Страница 3 из 3  [ Сообщений: 62 ]  на страницу...   1  2  3

   Похожие топики   Автор   Ответы   Просмотры   Последнее сообщение 
В этой теме нет новых непрочитанных сообщений. Тумбочка из хлама | LED ~ 220 watt | ВШГ 60x60x30

в форуме Строй-репорт

pickupbong

7

1367

06.11.19 14:17

pickupbong Перейти к последнему сообщению

В этой теме нет новых непрочитанных сообщений. Damnesia fem, тумбочка, COB 50W, LST, земля, Hesi

в форуме Grow reports

КаннаКот

23

1716

29.08.22 16:45

КаннаКот Перейти к последнему сообщению

В этой теме нет новых непрочитанных сообщений. Auto Amnesia / Тумбочка / Бытовые LED 118w / Земля / GHE

в форуме Grow Autoflowers

plazmogun

24

4033

23.07.21 14:24

olkalone Перейти к последнему сообщению

В этой теме нет новых непрочитанных сообщений. Auto Amnesia / Тумбочка 40х40х70 / Бытовые LED 173w / Земля / GHE

[ на страницу...: 1, 2, 3 ]

в форуме Grow Autoflowers

plazmogun

60

6341

15.11.20 07:01

AndyDance Перейти к последнему сообщению

В этой теме нет новых непрочитанных сообщений. Auto Daiquiri Lime / Тумбочка 40х40х70 / Бытовые LED 104w / Земля / GHE

[ на страницу...: 1, 2, 3 ]

в форуме Grow LED

plazmogun

64

6027

10.02.21 17:12

plazmogun Перейти к последнему сообщению



Журнал вахтёра

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения

Перейти:  
Powered by phpBB® Forum Software © phpBB Group

M