hyperion-project / hyperion.ng

The successor to Hyperion aka Hyperion Next Generation
https://hyperion-project.org/
MIT License
3.11k stars 384 forks source link

Add ambient light level readings #166

Closed penfold42 closed 7 years ago

penfold42 commented 8 years ago

We shoiuld look at integrating ambient light level readings to Hyperion.

Needs a flexible architecture to support easy addition of hardware type: Simple gpio digital pin I2c devices a-d converters I2c lux sensors

It seems like putting it in the transform code path is the best spot.. Scale brightens based on sensor reading

penfold42 commented 8 years ago

@redPanther - can you think of a neat way to integrate these sensors into the transform code path and options ?

Hyperion-Bot commented 8 years ago

We should have events (signal slots) in interresting code parts. Then we need some structure like leddevices, but with multiple devices that offer slots and events. Then a config where you can interconnect the input devices with hyperion events/hooks.

I have a concept in mind, but needs time for write it down.

Sorry for schortness message send via phone.

Greetz, rp

penfold42 commented 8 years ago

When did you become a bot?

I'll start at the bottom providing some basic classes and config parser.

redPanther commented 8 years ago

I wrote from trello, this is the github sync bot. Would be nice if you are there to. This is mainly a scrum/kanban board

redPanther commented 8 years ago

Just a crazy idea. What about using a v4l webcam as light sensor. Just take a picture with very low framerate and calculate amount of lightness.

penfold42 commented 8 years ago

Not so crazy ! Pi camera too

tpmodding commented 8 years ago

isn't a webcam to expensive? a lux sensor is much cheaper. but how will you handle this if you watch a action movie with explosions and the whole room is "yellow/red" :D

brindosch commented 8 years ago

I also see the light level reading idea not that easy. The idea itself is great, but you need to place it somewhere where you get always the appropriate values. I would prefer a sunset value based on your location. You need no hardware and it works also independendt across seasons (summer/winter)

Paulchen-Panther commented 8 years ago

@brindosch +1

redPanther commented 8 years ago

Take the readings when nothing is active and do not modify brigthness when movie plays. I got my webcam for 10€ from amazon. Arduino + analogue sensor is not much cheaper and it needs more DIY work. Disadvantage: it is not always possible to use more then one v4l device. But if no v4l grabber is used a webcam is definitely an option.

redPanther commented 8 years ago

I got this nice light sensor https://www.amazon.de/gp/product/B0178HMPJG

... mainly for my weather station, but at first I will try it with my arduino+leds. The sensor is i2c. I plan to extend adalight sketch and make continuous reading of the sensor. then map the readed value to fastled setBrightness function.

This is not a solution for hyperion itself, but For getting a feeling how this topic can be handled it should be enough.

redPanther commented 8 years ago

I just tried out my suggested test. I done my first test and it generally works. The sensor behaves quite well. But reading from sensor takes a bit time and this is leads to freeze leds for a short time (less 1s). If we want something like that in hyperion we definitly need filters to smooth the sensor readings. And every sensor should have it's own thread.

redPanther commented 7 years ago

an idea:

Cool thing is, it's standalone, so you can put it everywhere, regardless where your hyperion is installed -> imagine a pi on your balcony to measure light intensity and then controls the hyperion on your media pi on the back of your tv ....

The framework can be used for endless things ..

Here this is an example for connecting to json server and retrieve data: (please mention that this example do not use websockets - (this is more relaiable) )

#!/usr/bin/python2

import socket, sys

HOST = 'localhost'
PORT = 19444
conn = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM):
    af, socktype, proto, canonname, sa = res
    try:
        conn = socket.socket(af, socktype, proto)
    except socket.error as msg:
        conn = None
        continue
    try:
        conn.connect(sa)
    except socket.error as msg:
        conn.close()
        conn = None
        continue
    break

if conn is None:
    print 'could not open socket'
    sys.exit(1)

conn.sendall('{"command": "sysinfo"}\n')
data = ""
while 1:
    data += conn.recv(1024)
    if data.find("\n") >= 0 :
        break
print (repr(data))

conn.close()
redPanther commented 7 years ago

I think we are done here. With latest pr brightness works like a charm. Here is a script to controll brightness from a python script. instead of the slider you can read out r.g. via an arduino, or rpi gpio a light sensor and map the values from 0 to 100

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import signal, os, socket, sys, math
import tkinter as tk

class MainWindow(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        self.conn = None

        self.sliderBmax = tk.Scale(self.parent, from_=0, to=100, orient="horizontal", length=400)
        self.sliderBmax.set(100)
        self.sliderBmax.bind("<ButtonRelease-1>", self.updateValue)
        self.sliderBmax.pack()

    def updateValue(self, event):
        self.sendToHyperion(self.sliderBmax.get())

    def on_close(self,event=None):
        if self.conn is not None: self.conn.close()
        self.parent.destroy()

    def sendToHyperion(self, b):
        HOST = 'localhost'
        PORT = 19444
        if self.conn is None:
            for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM):
                af, socktype, proto, canonname, sa = res
                try:
                    self.conn = socket.socket(af, socktype, proto)
                except socket.error as msg:
                    self.conn = None
                    continue
                try:
                    self.conn.connect(sa)
                except socket.error as msg:
                    self.conn.close()
                    self.conn = None
                    continue
                break

        if self.conn is None:
            print ('could not open socket')
            return

        x = '{"adjustment": {"brightness":'+str(b)+'},"command": "adjustment"}\n'
        self.conn.sendall(bytes(x, "UTF-8"))

def signal_handler(signum, frame):
    exit(0)

signal.signal(signal.SIGINT, signal_handler)
root = tk.Tk()
app = MainWindow(parent=root)
root.protocol("WM_DELETE_WINDOW", app.on_close)
app.mainloop()