def __init__(self, *args, **kwargs): """ @TODO: perform LAN discovery, interrogate the resources, generate controls for all of them """ self.led_strip = LEDStrip(RESOLVED_USER_SETTINGS) RaspberryPiWebResource.__init__( self, *args, **kwargs) # Super, deals with generating the static directory etc
def __init__(self, *args, **kwargs): """ @TODO: perform LAN discovery, interrogate the resources, generate controls for all of them """ self.led_strip = LEDStrip(RESOLVED_USER_SETTINGS) Resource.__init__(self, *args, **kwargs) #Super # Add in the static folder. static_folder = os.path.join(RASPILED_DIR,"static") self.putChild("static", File(static_folder)) # Any requests to /static serve from the filesystem.
def render_css(self): """ Generates a CSS gradient from the self.display_gradient list """ if self.display_gradient: return "background: linear-gradient(-40deg, {colour_values}); color: white; text-shadow: 2px 2px 2px #000000".format(colour_values=self.colour) if self.display_colour: contrast_colour = LEDStrip.contrast_from_bg(col=self.colour, dark_default="202020") return "background: {display_colour}; color: {contrast_colour}".format( display_colour=self.colours_for_css_background(), contrast_colour=contrast_colour ) return ""
print(content['colour']) strip.setcolourhex(content['colour'][1:]) return 'Completed Successfully' elif 'period' in content.keys(): period = float(content['period']) print("Period set") return 'Set period time to {}s'.format(period) else: cycler = False print(content) cycler = True print(gradient_cycler(content['gradient'])) return 'Stopped gradient' @app.route('/') def main(): return render_template('index.html') if __name__ == "__main__": step_size = int(sys.argv[2]) period = 0.05 CLK = 18 DAT = 17 strip = LEDStrip(CLK, DAT) app.run(host=sys.argv[1], port=80)
#!/usr/bin/python from ledstrip import LEDStrip strip = LEDStrip() strip.off() strip.update()
#!/usr/bin/python from time import sleep from ledstrip import LEDStrip strip = LEDStrip() min = 36 max = 140 b = 40 speed = 1 dir = 1 while True: if b <= min: dir = 1 elif b >= max: dir = -1 b += dir * speed if b > 255: b = 255 elif b < 0: b = 0 for i in xrange(105): strip.set(i, b, 0, 0) strip.update() sleep(0.08)
class RaspiledControlResource(RaspberryPiWebResource): """ Our web page for controlling the LED strips """ led_strip = None # Populated at init # State what params should automatically trigger actions. If none supplied will show a default page. Specified in order of hierarchy PARAM_TO_ACTION_MAPPING = ( # Stat actions ("off", "off"), ("stop", "stop"), ("set", "set"), ("fade", "fade"), ("color", "fade"), ("colour", "fade"), # Sequences ("sunrise", "sunrise"), ("morning", "sunrise"), ("dawn", "sunrise"), ("sunset", "sunset"), ("evening", "sunset"), ("dusk", "sunset"), ("night", "sunset"), ("jump", "jump"), ("rotate", "rotate"), ("rot", "rotate"), ("huerot", "rotate"), ("colors", "rotate"), ("colours", "rotate"), # Docs: ("capabilities", "capabilities"), ("capability", "capabilities"), ("status", "status"), ) # State what presets to render: OFF_PRESET = Preset(label="""<img src="/static/figs/power-button-off.svg" class="icon_power_off"> Off""", display_colour="black", off="") PRESETS = { "Whites": ( # I've had to change the displayed colours from the strip colours for a closer apparent match Preset(label="Candle", display_colour="1500K", fade="1000K"), Preset(label="Tungsten", display_colour="3200K", fade="2000K"), Preset(label="Bulb match", display_colour="3900K", fade="ff821c"), Preset(label="Warm white", display_colour="4800K", fade="2600k"), # Bulb match Preset(label="Strip white", display_colour="6000K", fade="3200K"), Preset(label="Daylight", display_colour="6900K", fade="5800K"), Preset(label="Cool white", display_colour="9500K", fade="10500K"), ), "Sunrise / Sunset": ( Preset(label="↑ 2hr", display_gradient=("2000K", "5000K"), sunrise=60 * 60 * 2, is_sequence=True, is_sun=True), Preset(label="↑ 1hr", display_gradient=("2000K", "5000K"), sunrise=60 * 60 * 1, is_sequence=True, is_sun=True), Preset(label="↑ 30m", display_gradient=("2000K", "5000K"), sunrise=60 * 30, is_sequence=True, is_sun=True), Preset(label="↑ 1m", display_gradient=("2000K", "5000K"), sunrise=60 * 1, is_sequence=True, is_sun=True), PresetSpace(), Preset(label="↓ 1m", display_gradient=("5000K", "2000K"), sunset=60 * 1, is_sequence=True, is_sun=True), Preset(label="↓ 30m", display_gradient=("5000K", "2000K"), sunset=60 * 30, is_sequence=True, is_sun=True), Preset(label="↓ 1hr", display_gradient=("5000K", "2000K"), sunset=60 * 60 * 1, is_sequence=True, is_sun=True), Preset(label="↓ 2hr", display_gradient=("5000K", "2000K"), sunset=60 * 60 * 2, is_sequence=True, is_sun=True), ), "Colours": ( Preset(label="Red", display_colour="#FF0000", fade="#FF0000"), Preset(label="Orange", display_colour="#FF8800", fade="#FF8800"), Preset(label="Yellow", display_colour="#FFFF00", fade="#FFFF00"), Preset(label="Lime", display_colour="#88FF00", fade="#88FF00"), Preset(label="Green", display_colour="#00BB00", fade="#00FF00"), Preset(label="Aqua", display_colour="#00FF88", fade="#00FF88"), Preset(label="Cyan", display_colour="#00FFFF", fade="#00FFFF"), Preset(label="Blue", display_colour="#0088FF", fade="#0088FF"), Preset(label="Indigo", display_colour="#0000FF", fade="#0000FF"), Preset(label="Purple", display_colour="#8800FF", fade="#7A00FF"), # There's a difference! Preset(label="Magenta", display_colour="#FF00FF", fade="#FF00FF"), Preset(label="Crimson", display_colour="#FF0088", fade="#FF0088"), PresetRow(), Preset(label="Tasty Teal", display_colour="#009882", fade="#00FF3C"), Preset(label="Super Crimson", display_colour="#FF0077", fade="#FF0033"), ), "Sequences": ( Preset(label="🔥 Campfire", display_gradient=("600K", "400K", "1000K", "400K"), rotate="700K,500K,1100K,600K,800K,1000K,500K,1200K", milliseconds="1800", is_sequence=True), Preset(label="🐟 Fish tank", display_gradient=("#00FF88", "#0088FF", "#007ACC", "#00FFFF"), rotate="00FF88,0088FF,007ACC,00FFFF", milliseconds="2500", is_sequence=True), Preset(label="🎉 Party", display_gradient=("cyan", "yellow", "magenta"), rotate="cyan,yellow,magenta", milliseconds="1250", is_sequence=True), Preset(label="🌻 Flamboyant", display_gradient=("yellow", "magenta"), jump="yellow,magenta", milliseconds="150", is_sequence=True), Preset(label="🎄 Christmas", display_gradient=("green", "red"), rotate="green,red", milliseconds="300", is_sequence=True), Preset(label="🚨 NeeNaw", display_gradient=("cyan", "blue"), jump="cyan,blue", milliseconds="100", is_sequence=True), Preset(label="🚨 NeeNaw USA", display_gradient=("red", "blue"), jump="red,blue", milliseconds="100", is_sequence=True), Preset(label="🌈 Full circle", display_gradient=( "#FF0000", "#FF8800", "#FFFF00", "#88FF00", "#00FF00", "#00FF88", "#00FFFF", "#0088FF", "#0000FF", "#8800FF", "#FF00FF", "#FF0088"), milliseconds=500, rotate="#FF0000,FF8800,FFFF00,88FF00,00FF00,00FF88,00FFFF,0088FF,0000FF,8800FF,FF00FF,FF0088", is_sequence=True), ) } PRESETS_COPY = copy.deepcopy(PRESETS) # Modifiable dictionary. Used in alarms and music. def __init__(self, *args, **kwargs): """ @TODO: perform LAN discovery, interrogate the resources, generate controls for all of them """ self.led_strip = LEDStrip(RESOLVED_USER_SETTINGS) RaspberryPiWebResource.__init__(self, *args, **kwargs) # Super, deals with generating the static directory etc def render_controls(self, request): """ Show the main controls screen """ context = { "off_preset_html": self.OFF_PRESET.render(), "light_html": self.render_light_presets(request), "alarm_html": self.render_alarm_presets(request), "music_html": self.render_udevelop_presets(request), "controls_html": self.render_udevelop_presets(request), } return RaspberryPiWebResource.render_controls(self, request, context) #### Additional pages available via the menu #### def render_light_presets(self, request): """ Renders the light presets as options @param request: The http request object """ out_html_list = [] for group_name, presets in self.PRESETS.items(): preset_list = [] # Inner for for preset in presets: preset_html = preset.render() preset_list.append(preset_html) group_html = """ <div class="preset_group"> <h2>{group_name}</h2> <div class="presets_row"> {preset_html} </div> </div> """.format( group_name=group_name, preset_html="\n".join(preset_list) ) out_html_list.append(group_html) out_html = "\n".join(out_html_list) return out_html def render_alarm_presets(self, request): """ Renders the alarm presets as options. Same sunrise or sunset routine except for 100k. """ out_html_list = [] preset_list = [] # Inner for group_name = "Sunrise / Sunset" presets = self.PRESETS_COPY[group_name] for preset in presets: try: if preset.display_gradient[0] == '5000K': preset.display_gradient = ('5000K', '50K') else: preset.display_gradient = ('50K', '5000K') except: pass preset_html = preset.render() preset_list.append(preset_html) group_html = """ <p id="clock" class="current-colour"></p> <h2>{group_name}</h2> <div class="sun-alarm" data-latitude="{users_latitude}" data-longitude="{users_longitude}"></div> <div class="preset_group"> <div class="presets_row"> {preset_html} </div> </div> """.format( group_name=group_name, preset_html="\n".join(preset_list), users_latitude=get_setting("latitude", 52.2053), users_longitude=get_setting("longitude", 0.1218) ) out_html_list.append(group_html) out_html = "\n".join(out_html_list) return out_html def render_udevelop_presets(self, request): """ Renders the Under Development text. """ out_html = """ <div class="underdevelop"> <h1> Under Development, please refer to the Github repository.</h1> </div> """ return out_html # Actions: These are the actions our web server can initiate. Triggered by hitting the url with ?action_name=value #### def before_action(self, *args, **kwargs): """ Called just before an action takes place. We stop whatever current sequence is running """ self.led_strip.stop_current_sequence() # Stop current sequence def action__set(self, request): """ Run when user wants to set a colour to a specified value """ set_colour = request.get_param("set", force=unicode) D("Set to: %s" % set_colour) return self.led_strip.set(set_colour) action__set.capability = { "param": "set", "description": "Sets the RGB strip to a single colour.", "value": "<unicode> A named colour (e.g. 'pink') or colour hex value (e.g. '#19BECA').", "validity": "<unicode> A known named colour, or valid colour hex in the range #000000-#FFFFFF.", "widget": "colourpicker", "returns": "<unicode> The hex value of the colour the RGB strip has been set to." } def action__fade(self, request): """ Run when user wants to set a colour to a specified value """ fade_colour = request.get_param("fade", force=unicode) logging.info("Fade to: %s" % fade_colour) return self.led_strip.fade(fade_colour) action__fade.capability = { "param": "fade", "description": "Fades the RGB strip from its current colour to a specified colour.", "value": "<unicode> A named colour (e.g. 'pink') or colour hex value (e.g. '#19BECA').", "validity": "<unicode> A known named colour, or valid colour hex in the range #000000-#FFFFFF", "returns": "<unicode> The hex value of the colour the RGB strip has been set to." } def action__sunrise(self, request): """ Performs a sunrise over the specified period of time """ seconds = request.get_param(["seconds", "s", "sunrise"], default=10.0, force=float) milliseconds = request.get_param(["milliseconds", "ms"], default=0.0, force=float) temp_start = request.get_param(['temp_start', 'K'], default=None, force=unicode) temp_end = request.get_param('temp_end', default=None, force=unicode) logging.info("Sunrise: %s seconds" % (seconds + (milliseconds / 1000.0))) return self.led_strip.sunrise(seconds=seconds, milliseconds=milliseconds, temp_start=temp_start, temp_end=temp_end) action__sunrise.capability = { "param": "sunrise", "description": "Gently fades-in the RGB strip from deep red to daylight.", "value": "The number of seconds you would like the sunrise to take.", "validity": "<float> > 0", "optional_concurrent_parameters": [ { "param": "milliseconds", "value": "The number of milliseconds the sunrise should take. Will be added to seconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "1000", }, { "param": "temp_start", "value": "The colour temperature you wish to start from (e.g. 500K).", "validity": "<unicode> Matches a named colour temperature (50K - 15000K in 100 Kelvin steps)", "default": "6500K" }, { "param": "temp_end", "value": "The colour temperature you wish to finish at (e.g. 4500K).", "validity": "<unicode> Matches a named colour temperature (50K - 15000K in 100 Kelvin steps)", "default": "500K" } ], "returns": "<unicode> The hex value of the colour the RGB strip has been set to." } def action__sunset(self, request): """ Performs a sunset over the specified period of time """ seconds = request.get_param(["seconds", "s", "sunset"], default=10.0, force=float) milliseconds = request.get_param(["milliseconds", "ms"], default=0.0, force=float) temp_start = request.get_param(['temp_start', 'K'], default=None, force=unicode) temp_end = request.get_param('temp_end', default=None, force=unicode) logging.info("Sunset: %s seconds" % (seconds + (milliseconds / 1000.0))) return self.led_strip.sunset(seconds=seconds, milliseconds=milliseconds, temp_start=temp_start, temp_end=temp_end) action__sunset.capability = { "param": "sunset", "description": "Gently fades-out the RGB strip from daylight to deep-red.", "value": "The number of seconds you would like the sunrise to take.", "validity": "<float> > 0", "optional_concurrent_parameters": [ { "param": "milliseconds", "value": "The number of milliseconds the sunset should take. Will be added to seconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "1000", }, { "param": "temp_start", "value": "The colour temperature you wish to start from (e.g. 500K).", "validity": "<unicode> Matches a named colour temperature (50K - 15000K in 100 Kelvin steps)", "default": "500K" }, { "param": "temp_end", "value": "The colour temperature you wish to finish at (e.g. 4500K).", "validity": "<unicode> Matches a named colour temperature (50K - 15000K in 100 Kelvin steps)", "default": "6500K" } ], "returns": "" } def action__jump(self, request): """ Jump from one specified colour to the next """ jump_colours = request.get_param_values("jump") seconds = request.get_param(["seconds", "s"], default=0.0, force=float) milliseconds = request.get_param(["milliseconds", "ms"], default=0.0, force=float) self.led_strip.stop_current_sequence() # Terminate any crap that's going on total_seconds = (seconds + (milliseconds / 1000.0)) logging.info("Jump: %s, %s seconds" % (jump_colours, total_seconds)) return self.led_strip.jump(jump_colours, seconds=seconds, milliseconds=milliseconds) # Has its own colour sanitisation routine action__jump.capability = { "param": "jump", "description": "Hops from one colour to the next over an even period of time.", "value": "A comma delimited list of colours you wish to jump between.", "validity": "<unicode> valid colour names or hex values separated by commas (e.g. red,blue,green,cyan,#FF00FF)", "optional_concurrent_parameters": [ { "param": "milliseconds", "value": "The number of milliseconds the each colour should be displayed for. Will be added to seconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "200", }, { "param": "seconds", "value": "The number of seconds each colour should be displayed for. Will be added to milliseconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "0", }, ], "returns": "<unicode> The first hex value of sequence." } def action__rotate(self, request): """ Rotates (fades) from one specified colour to the next """ rotate_colours = request.get_param_values("rotate") seconds = request.get_param(["seconds", "s"], default=0.0, force=float) milliseconds = request.get_param(["milliseconds", "ms"], default=0.0, force=float) self.led_strip.stop_current_sequence() # Terminate any crap that's going on total_seconds = (seconds + (milliseconds / 1000.0)) logging.info("Rotate: %s, %s seconds" % (rotate_colours, total_seconds)) return self.led_strip.rotate(rotate_colours, seconds=seconds, milliseconds=milliseconds) # Has its own colour sanitisation routine action__rotate.capability = { "param": "rotate", "description": "Fades from one colour to the next over an even period of time.", "value": "A comma delimited list of colours you wish to cross-fade between.", "validity": "<unicode> valid colour names or hex values separated by commas (e.g. red,blue,green,cyan,#FF00FF)", "optional_concurrent_parameters": [ { "param": "milliseconds", "value": "The number of milliseconds the each colour fade should take. Will be added to seconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "200", }, { "param": "seconds", "value": "The number of seconds each colour fade should take. Will be added to milliseconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "0", }, ], "returns": "<unicode> The first hex value of sequence." } def action__stop(self, request): """ Stops the current sequence """ return self.led_strip.stop() action__stop.capability = { "param": "stop", "description": "Halts the current sequence or fade.", "value": "", "returns": "<unicode> The hex value of colour the RGB strip got halted on." } def action__off(self, request): """ Turns the strip off """ logging.info("Off!") return self.led_strip.off() action__off.capability = { "param": "off", "description": "Stops any fades or sequences. Quickly Fades the RGB strip to black (no light)", "value": "", "returns": "<unicode> The hex value of colour the RGB strip ends up at (#000000)." } def information__status(self, request, *args, **kwargs): """ Reports the status of the RGB LED strip """ current_rgb = "({})".format(self.led_strip) current_hex = self.led_strip.hex contrast_colour = self.led_strip.contrast_from_bg(current_hex, dark_default="202020") return { "sequence": self.led_strip.sequence_colours, "current_hex": current_hex, "current": current_rgb, "current_colour": current_rgb, "current_rgb": current_rgb, "contrast": contrast_colour, "contrast_colour": contrast_colour } def teardown(self): """ Called automatically when exiting the parent reactor """ self.led_strip.teardown()
#!/usr/bin/python from ledstrip import LEDStrip strip = LEDStrip() for i in xrange(105): strip.set(i, 255, 255, 255) strip.update()
#!/usr/bin/python import time from flask import Flask, request from ledstrip import LEDStrip CLK = 17 DAT = 18 strip = LEDStrip(CLK, DAT) app = Flask(__name__) strip.setcolourred() time.sleep(0.2) strip.setcolourgreen() time.sleep(0.2) strip.setcolourblue() time.sleep(0.2) strip.setcolouroff() @app.route("/") def hello(): strip.setcolouroff() return "Hello World!" @app.route("/red") def redled(): strip.setcolourred() return "red"
import time from neopixel import * from flask import Flask from ledstrip import LEDStrip from get_color import get_color import argparse import signal import sys app = Flask(__name__) led_strip = LEDStrip(18, 60) @app.route('/colorwipe/<string:color>') def colorWipe(color): led_strip.colorWipe(get_color(color)) return 'color wipe activated' @app.route('/colorswipe/<string:color1>&<string:color2>') def colorsWipe(color1, color2): led_strip.twoColorWipe(get_color(color1), get_color(color2)) return 'color wipe activated' @app.route('/rainbow') def rainbow():
class RaspiledControlResource(Resource): """ Our web page for controlling the LED strips """ isLeaf = False # Allows us to go into dirs led_strip = None # Populated at init _path = None # If a user wants to hit a dynamic subpage, the path appears here PARAM_TO_AUTHENTICATE = ( ("user","newclient"), ("ukey","authenticate"), ) #State what params should automatically trigger actions. If none supplied will show a default page. Specified in order of hierarchy # State what params should automatically trigger actions. If none supplied will show a default page. Specified in order of hierarchy PARAM_TO_ACTION_MAPPING = ( # Stat actions ("off", "off"), ("stop", "stop"), ("set", "set"), ("fade", "fade"), ("color", "fade"), ("colour", "fade"), # Sequences ("sunrise", "sunrise"), ("morning", "alarm"), ("dawn", "alarm"), ("sunset", "sunset"), ("evening", "sunset"), ("dusk", "sunset"), ("night", "sunset"), ("jump", "jump"), ("rotate", "rotate"), ("rot", "rotate"), ("huerot", "rotate"), ("colors", "rotate"), ("colours", "rotate"), # Docs: ("capabilities", "capabilities"), ("capability", "capabilities"), ("status", "status"), ) # State what presets to render: OFF_PRESET = Preset(label="""<img src="/static/figs/power-button-off.svg" class="icon_power_off"> Off""", display_colour="black", off="") PRESETS = { "Whites":( #I've had to change the displayed colours from the strip colours for a closer apparent match Preset(label="Candle", display_colour="1500K", fade="1000K"), Preset(label="Tungsten", display_colour="3200K", fade="2000K"), Preset(label="Bulb match", display_colour="3900K", fade="ff821c"), Preset(label="Warm white", display_colour="4800K", fade="2600k"), #Bulb match Preset(label="Strip white", display_colour="6000K", fade="3200K"), Preset(label="Daylight", display_colour="6900K", fade="5800K"), Preset(label="Cool white", display_colour="9500K", fade="10500K"), ), "Sunrise / Sunset":( Preset(label="↑ 2hr", display_gradient=("2000K","5000K"), sunrise=60*60*2, is_sequence=True, is_sun=True), Preset(label="↑ 1hr", display_gradient=("2000K","5000K"), sunrise=60*60*1, is_sequence=True, is_sun=True), Preset(label="↑ 30m", display_gradient=("2000K","5000K"), sunrise=60*30, is_sequence=True, is_sun=True), Preset(label="↑ 1m", display_gradient=("2000K","5000K"), sunrise=60*1, is_sequence=True, is_sun=True), PresetSpace(), Preset(label="↓ 1m", display_gradient=("5000K","2000K"), sunset=60*1, is_sequence=True, is_sun=True), Preset(label="↓ 30m", display_gradient=("5000K","2000K"), sunset=60*30, is_sequence=True, is_sun=True), Preset(label="↓ 1hr", display_gradient=("5000K","2000K"), sunset=60*60*1, is_sequence=True, is_sun=True), Preset(label="↓ 2hr", display_gradient=("5000K","2000K"), sunset=60*60*2, is_sequence=True, is_sun=True), ), "Colours":( Preset(label="Red", display_colour="#FF0000", fade="#FF0000"), Preset(label="Orange", display_colour="#FF8800", fade="#FF8800"), Preset(label="Yellow", display_colour="#FFFF00", fade="#FFFF00"), Preset(label="Lime", display_colour="#88FF00", fade="#88FF00"), Preset(label="Green", display_colour="#00BB00", fade="#00FF00"), Preset(label="Aqua", display_colour="#00FF88", fade="#00FF88"), Preset(label="Cyan", display_colour="#00FFFF", fade="#00FFFF"), Preset(label="Blue", display_colour="#0088FF", fade="#0088FF"), Preset(label="Indigo", display_colour="#0000FF", fade="#0000FF"), Preset(label="Purple", display_colour="#8800FF", fade="#7A00FF"), # There's a difference! Preset(label="Magenta", display_colour="#FF00FF", fade="#FF00FF"), Preset(label="Crimson", display_colour="#FF0088", fade="#FF0088"), ), "Sequences":( Preset(label="🔥 Campfire", display_gradient=("600K","400K","1000K","400K"), rotate="1100K,800K,1100K,1300K,1300K,900K,1500K,800K,900K,800K,1300K,600K,600K,600K,900K,600K,900K,1100K,1400K,1400K,900K,800K,600K,700K,700K,900K,1000K,1000K,800K,900K,1000K,700K,900K,1000K,600K,700K,1000K,800K,800K,1400K,900K,1100K,1000K,1500K,1000K,1000K,900K,700K", milliseconds="80", is_sequence=True), Preset(label="🐟 Fish tank", display_gradient=("#00FF88","#0088FF","#007ACC","#00FFFF"), rotate="00FF88,0088FF,007ACC,00FFFF", milliseconds="2500", is_sequence=True), Preset(label="🎉 Party", display_gradient=("cyan","yellow","magenta"), rotate="cyan,yellow,magenta", milliseconds="1250", is_sequence=True), Preset(label="🌻 Flamboyant", display_gradient=("yellow","magenta"), jump="yellow,magenta", milliseconds="150", is_sequence=True), Preset(label="🚨 NeeNaw", display_gradient=("cyan","blue"), jump="cyan,blue", milliseconds="100", is_sequence=True), Preset(label="🚨 NeeNaw USA", display_gradient=("red","blue"), jump="red,blue", milliseconds="100", is_sequence=True), Preset(label="🌈 Full circle", display_gradient=("#FF0000","#FF8800","#FFFF00","#88FF00","#00FF00","#00FF88","#00FFFF","#0088FF","#0000FF","#8800FF","#FF00FF","#FF0088"), milliseconds=500, rotate="#FF0000,FF8800,FFFF00,88FF00,00FF00,00FF88,00FFFF,0088FF,0000FF,8800FF,FF00FF,FF0088", is_sequence=True), ) } ALARM_PRESETS = { "Morning":( Preset(label="↑ 2hr", display_gradient=("0K","5000K"), morning=60*60*2, is_sequence=True, is_sun=True), Preset(label="↑ 1hr", display_gradient=("0K","5000K"), morning=60*60*1, is_sequence=True, is_sun=True), Preset(label="↑ 30m", display_gradient=("0K","5000K"), morning=60*30, is_sequence=True, is_sun=True), Preset(label="↑ 1m", display_gradient=("0K","5000K"), morning=60*1, is_sequence=True, is_sun=True), ), "Dawn":( Preset(label="↓ 2hr", display_gradient=("5000K","0K"), dawn=60*60*2, is_sequence=True, is_sun=True), Preset(label="↓ 1hr", display_gradient=("5000K","0K"), dawn=60*60*1, is_sequence=True, is_sun=True), Preset(label="↓ 30m", display_gradient=("5000K","0K"), dawn=60*30, is_sequence=True, is_sun=True), Preset(label="↓ 1m", display_gradient=("5000K","0K"), dawn=60*1, is_sequence=True, is_sun=True), ) } PRESETS_COPY = copy.deepcopy(PRESETS) # Modifiable dictionary. Used in alarms and music. def __init__(self, *args, **kwargs): """ @TODO: perform LAN discovery, interrogate the resources, generate controls for all of them """ self.led_strip = LEDStrip(RESOLVED_USER_SETTINGS) Resource.__init__(self, *args, **kwargs) #Super # Add in the static folder. static_folder = os.path.join(RASPILED_DIR,"static") self.putChild("static", File(static_folder)) # Any requests to /static serve from the filesystem. def getChild(self, path, request, *args, **kwargs): """ Entry point for dynamic pages """ self._path = path return self def getChildWithDefault(self, path, request): """ Retrieve a static or dynamically generated child resource from me. First checks if a resource was added manually by putChild, and then call getChild to check for dynamic resources. Only override if you want to affect behaviour of all child lookups, rather than just dynamic ones. This will check to see if I have a pre-registered child resource of the given name, and call getChild if I do not. @see: L{IResource.getChildWithDefault} """ if path in self.children: return self.children[path] return self.getChild(path, request) def client_LOGIN(self, request): accepted_connection=False self.ip=request.getClientIP() self.session_data = { '0':{ 'user' : 'pi', 'psw' : '', 'ip' : ['127.0.0.1'], 'key' : '', 'last_c': '', 'u_key' : '', } } if os.path.exists(wlist_path): with open(wlist_path) as json_data: self.session_data = json.load(json_data) else: self.whitelistjson2file() for key, value in self.session_data.items(): if accepted_connection==True: break for ip in value['ip']: if self.ip==ip: accepted_connection=True break return accepted_connection def render_GET(self, request): """ MAIN WEB PAGE ENTRY POINT Responds to GET requests If a valid action in the GET querystring is present, that action will get performed and the web server will return a JSON response. The assumption is that a javascript function is calling this web server to act as an API If a human being arrives at the web server without providing a valid action in the GET querystring, they'll just be given the main html page which shows all the buttons. @param request: The http request, passed in from Twisted, which will be an instance of <SmartRequest> @return: HTML or JSON depending on if there is no action or an action. """ accepted_client = self.client_LOGIN(request) if accepted_client: _colour_result = None #Look through the actions if the request key exists, perform that action for key_name, action_name in self.PARAM_TO_ACTION_MAPPING: if request.has_param(key_name): self.led_strip.stop_current_sequence() #Stop current sequence action_func_name = "action__%s" % action_name _colour_result = getattr(self, action_func_name)(request) #Execute that function break # Look through the actions if the request key exists, perform that action clean_path = unicode(self._path or u"").rstrip("/") for key_name, action_name in self.PARAM_TO_ACTION_MAPPING: if request.has_param(key_name) or clean_path == key_name: action_func_name = "action__%s" % action_name if action_name in ("capabilities", "status"): # Something is asking for our capabilities or status output = getattr(self, action_func_name)(request) # Execute that function request.setHeader("Content-Type", "application/json; charset=utf-8") return json.dumps(output) else: self.led_strip.stop_current_sequence() #Stop current sequence _colour_result = getattr(self, action_func_name)(request) #Execute that function break # Now deduce our colour: current_colour = "({})".format(self.led_strip) current_hex = self.led_strip.hex contrast_colour = self.led_strip.contrast_from_bg(current_hex, dark_default="202020") # Return a JSON object if an action has been performed (i.e. _colour_result is set): if _colour_result is not None: json_data = { "current" : current_hex, "contrast" : contrast_colour, "current_rgb": current_colour } try: request.setHeader("Content-Type", "application/json; charset=utf-8") return json.dumps(json_data) except (TypeError, ValueError): return b"Raspiled generated invalid JSON data!" # Otherwise, we've not had an action, so return normal page request.setHeader("Content-Type", "text/html; charset=utf-8") htmlstr = '' with open(RASPILED_DIR+'/static/index.html') as index_html_template: htmlstr = index_html_template.read() # 2018-09-08 It's more efficient to pull the whole file in return htmlstr.format( current_colour=current_colour, current_hex=current_hex, contrast_colour=contrast_colour, off_preset_html=self.OFF_PRESET.render(), light_html=self.light_presets(request), alarm_html=self.alarm_presets(request), music_html=self.music_presets(request), controls_html=self.udevelop_presets(request), addition_js=self.js_interactions(request) ).encode('utf-8') else: # Authenticatiom _connection_result=None for key_name, action_name in self.PARAM_TO_AUTHENTICATE: if request.has_param(key_name): action_func_name = "action__%s" % action_name _connection_result = getattr(self, action_func_name)(request) break if _connection_result is not None: try: return json.dumps(_connection_result) except: return b"Json fkucked up" request.setHeader("Content-Type", "text/html; charset=utf-8") htmlstr='' with open(RASPILED_DIR+'/static/singin.html') as file: for line in file: htmlstr+=line return htmlstr.encode('utf-8') def action__newclient(self,request): """ Push a new client to the autentication or appends the new ip to the dictionary of sessions. """ self.user = request.get_param("user", force=unicode) self.pswd = request.get_param("pswd", force=unicode) if (self.user==None or self.pswd == None ): pass elif (self.user=='' or self.pswd == '' ): return {'error':True,'message':'Empty user or password','accepted':False,'authentication':False} else: csession = request.getSession() self.key = csession.uid for key, value in self.session_data.items(): if value['user'] == self.user and value['psw'] == self.pswd: value['ip'].append(self.ip) self.whitelistjson2file() return {'error':False,'message':'Success','accepted':True,'authentication':False} self.ukey = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(10)) logging.info("Attempt from user: %s with IP: %s to access the server. Unique key: %s" % (self.user,self.ip,self.ukey)) return {'error':False,'message':'Authenticate','accepted':False,'authentication':True} def action__authenticate(self,request): """ Client authenticate with random string generated in the server """ user_ukey = request.get_param("ukey", force=unicode) if self.ukey == user_ukey: self.session_data[str(len(self.session_data.keys()))]={ 'user' : self.user, 'psw' : self.pswd, 'ip' : [self.ip], 'key' : self.key, 'last_c': str(datetime.datetime.now()), 'u_key' : self.ukey, } self.whitelistjson2file() return {'error':False,'message':'Success','accepted':True,'authentication':False} else: self.ukey=''.join(random.SystemRandom().choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(10)) logging.info("New unique key: %s" % self.ukey) return {'error':True,'message':'New authenticate code','accepted':False,'authentication':True} def whitelistjson2file(self): with open(wlist_path, 'w') as write_file: json.dump(self.session_data, write_file) #### Additional pages available via the menu #### def light_presets(self, request): """ Renders the light presets as options @param request: The http request object """ out_html_list = [] for group_name, presets in self.PRESETS.items(): preset_list = [] #Inner for for preset in presets: preset_html = preset.render() preset_list.append(preset_html) group_html = """ <div class="preset_group"> <h2>{group_name}</h2> <div class="presets_row"> {preset_html} </div> </div> """.format( group_name = group_name, preset_html = "\n".join(preset_list) ) out_html_list.append(group_html) out_html = "\n".join(out_html_list) return out_html def alarm_presets(self,request): """ Renders the alarm presets as options. Same sunrise or sunset routine except for 100k. """ out_html_list = [] for group_name, presets in self.ALARM_PRESETS.items(): preset_list = [] for preset in presets: preset_html = preset.render_select() preset_list.append(preset_html) group_html = """ <p> {group_name} time </p> <div class="{group_name}"></div> <div class="preset_group"> <select class="presets_select {group_name}_select"> {preset_html} </select> </div> """.format( group_name = group_name, preset_html = "\n".join(preset_list), ) out_html_list.append(group_html) out_html = "\n".join(out_html_list) return out_html def music_presets(self,request): """ Renders the Modipy music front page. """ #out_html=""" # <iframe src="http://192.168.182.190:{mopify}/mopify/" style="width:100vw;height:100vh"> # </iframe> #""".format(mopify=params['mopidy_port']) #return out_html pass def udevelop_presets(self,request): """ Renders the Under Development text. """ out_html=""" <div class="underdevelop"> <h1> Under Development, please refer to the Github repository.</h1> </div> """ return out_html def js_interactions(self,request): request.setHeader("Content-Type", "text/html; charset=utf-8") if params['latitude'] == '' or params['longitude'] == '': lat,lon=pi_gps_location() else: lat=params['latitude'] lon=params['longitude'] jsstr='' with open(RASPILED_DIR+'/static/js/raspiled_interaction.js') as file: for line in file: jsstr+=line return jsstr.format(latcoord=str(lat),loncoord=str(lon)).encode('utf-8') #### Actions: These are the actions our web server can initiate. Triggered by hitting the url with ?action_name=value #### def action__set(self, request): """ Run when user wants to set a colour to a specified value """ set_colour = request.get_param("set", force=unicode) D("Set to: %s" % set_colour) return self.led_strip.set(set_colour) action__set.capability = { "param": "set", "description": "Sets the RGB strip to a single colour.", "value": "<unicode> A named colour (e.g. 'pink') or colour hex value (e.g. '#19BECA').", "validity": "<unicode> A known named colour, or valid colour hex in the range #000000-#FFFFFF.", "widget": "colourpicker", "returns": "<unicode> The hex value of the colour the RGB strip has been set to." } def action__fade(self, request): """ Run when user wants to set a colour to a specified value """ fade_colour = request.get_param("fade", force=unicode) logging.info("Fade to: %s" % fade_colour) return self.led_strip.fade(fade_colour) action__fade.capability = { "param": "fade", "description": "Fades the RGB strip from its current colour to a specified colour.", "value": "<unicode> A named colour (e.g. 'pink') or colour hex value (e.g. '#19BECA').", "validity": "<unicode> A known named colour, or valid colour hex in the range #000000-#FFFFFF", "returns": "<unicode> The hex value of the colour the RGB strip has been set to." } def action__sunrise(self, request): """ Performs a sunrise over the specified period of time """ seconds = request.get_param(["seconds","s","sunrise"], default=10.0, force=float) milliseconds = request.get_param(["milliseconds","ms"], default=0.0, force=float) temp_start = request.get_param(['temp_start','K'], default=None, force=unicode) temp_end = request.get_param('temp_end', default=None, force=unicode) logging.info("Sunrise: %s seconds" % (seconds + (milliseconds/1000.0))) return self.led_strip.sunrise(seconds=seconds, milliseconds=milliseconds, temp_start=temp_start, temp_end=temp_end) action__sunrise.capability = { "param": "sunrise", "description": "Gently fades-in the RGB strip from deep red to daylight.", "value": "The number of seconds you would like the sunrise to take.", "validity": "<float> > 0", "optional_concurrent_parameters": [ { "param": "milliseconds", "value": "The number of milliseconds the sunrise should take. Will be added to seconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "1000", }, { "param": "temp_start", "value": "The colour temperature you wish to start from (e.g. 500K).", "validity": "<unicode> Matches a named colour temperature (50K - 15000K in 100 Kelvin steps)", "default": "6500K" }, { "param": "temp_end", "value": "The colour temperature you wish to finish at (e.g. 4500K).", "validity": "<unicode> Matches a named colour temperature (50K - 15000K in 100 Kelvin steps)", "default": "500K" } ], "returns": "<unicode> The hex value of the colour the RGB strip has been set to." } def action__sunset(self, request): """ Performs a sunset over the specified period of time """ seconds = request.get_param(["seconds","s","sunset"], default=10.0, force=float) milliseconds = request.get_param(["milliseconds","ms"], default=0.0, force=float) temp_start = request.get_param(['temp_start', 'K'], default=None, force=unicode) temp_end = request.get_param('temp_end', default=None, force=unicode) logging.info("Sunset: %s seconds" % (seconds + (milliseconds/1000.0))) return self.led_strip.sunset(seconds=seconds, milliseconds=milliseconds, temp_start=temp_start, temp_end=temp_end) action__sunset.capability = { "param": "sunset", "description": "Gently fades-out the RGB strip from daylight to deep-red.", "value": "The number of seconds you would like the sunrise to take.", "validity": "<float> > 0", "optional_concurrent_parameters": [ { "param": "milliseconds", "value": "The number of milliseconds the sunset should take. Will be added to seconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "1000", }, { "param": "temp_start", "value": "The colour temperature you wish to start from (e.g. 500K).", "validity": "<unicode> Matches a named colour temperature (50K - 15000K in 100 Kelvin steps)", "default": "500K" }, { "param": "temp_end", "value": "The colour temperature you wish to finish at (e.g. 4500K).", "validity": "<unicode> Matches a named colour temperature (50K - 15000K in 100 Kelvin steps)", "default": "6500K" } ], "returns": "" } def action__alarm(self, request): """ Performs a sunrise over the specified period of time """ m_seconds = request.get_param(["seconds","s","morning"], default=10.0, force=float) d_seconds = request.get_param(["seconds","s","dawn"], default=10.0, force=float) hour = request.get_param(["time","hr","hour"], default='12:00', force=unicode) freq = request.get_param(["freq"], default='daily', force=float) milliseconds = request.get_param(["milliseconds","ms"], default=0.0, force=float) temp_start = request.get_param(['temp_start', 'K'], default=None, force=unicode) temp_end = request.get_param('temp_end', default=None, force=unicode) logging.info("Morning Alarm : %s seconds at %s" % (m_seconds + (milliseconds/1000.0), hour[0])) logging.info("Dawn Alarm : %s seconds at %s" % (d_seconds + (milliseconds/1000.0), hour[1])) return self.led_strip.alarm(seconds=[d_seconds,m_seconds], milliseconds=milliseconds, hour=hour, freq=freq, temp_start=temp_start, temp_end=temp_end) def action__jump(self, request): """ Jump from one specified colour to the next """ jump_colours = request.get_param_values("jump") seconds = request.get_param(["seconds","s"], default=0.0, force=float) milliseconds = request.get_param(["milliseconds","ms"], default=0.0, force=float) self.led_strip.stop_current_sequence() #Terminate any crap that's going on total_seconds = (seconds + (milliseconds/1000.0)) logging.info("Jump: %s, %s seconds" % (jump_colours, total_seconds)) return self.led_strip.jump(jump_colours, seconds=seconds, milliseconds=milliseconds) #Has its own colour sanitisation routine action__jump.capability = { "param": "jump", "description": "Hops from one colour to the next over an even period of time.", "value": "A comma delimited list of colours you wish to jump between.", "validity": "<unicode> valid colour names or hex values separated by commas (e.g. red,blue,green,cyan,#FF00FF)", "optional_concurrent_parameters": [ { "param": "milliseconds", "value": "The number of milliseconds the each colour should be displayed for. Will be added to seconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "200", }, { "param": "seconds", "value": "The number of seconds each colour should be displayed for. Will be added to milliseconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "0", }, ], "returns": "<unicode> The first hex value of sequence." } def action__rotate(self, request): """ Rotates (fades) from one specified colour to the next """ rotate_colours = request.get_param_values("rotate") seconds = request.get_param(["seconds","s"], default=0.0, force=float) milliseconds = request.get_param(["milliseconds","ms"], default=0.0, force=float) self.led_strip.stop_current_sequence() #Terminate any crap that's going on total_seconds = (seconds + (milliseconds/1000.0)) logging.info("Rotate: %s, %s seconds" % (rotate_colours, total_seconds)) return self.led_strip.rotate(rotate_colours, seconds=seconds, milliseconds=milliseconds) #Has its own colour sanitisation routine action__rotate.capability = { "param": "rotate", "description": "Fades from one colour to the next over an even period of time.", "value": "A comma delimited list of colours you wish to cross-fade between.", "validity": "<unicode> valid colour names or hex values separated by commas (e.g. red,blue,green,cyan,#FF00FF)", "optional_concurrent_parameters": [ { "param": "milliseconds", "value": "The number of milliseconds the each colour fade should take. Will be added to seconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "200", }, { "param": "seconds", "value": "The number of seconds each colour fade should take. Will be added to milliseconds (if specified) to give a total time.", "validity": "<int> > 0", "default": "0", }, ], "returns": "<unicode> The first hex value of sequence." } def action__stop(self, request): """ Stops the current sequence """ return self.led_strip.stop() action__stop.capability = { "param": "stop", "description": "Halts the current sequence or fade.", "value": "", "returns": "<unicode> The hex value of colour the RGB strip got halted on." } def action__off(self, request): """ Turns the strip off """ logging.info("Off!") return self.led_strip.off() action__off.capability = { "param": "off", "description": "Stops any fades or sequences. Quickly Fades the RGB strip to black (no light)", "value": "", "returns": "<unicode> The hex value of colour the RGB strip ends up at (#000000)." } def action__capabilities(self, request, *args, **kwargs): """ Reports this listener's capabilities """ output_capabilities = [] for function_name in dir(self): if function_name.startswith("action__"): try: capability_details = getattr(self,function_name).capability output_capabilities.append(capability_details) except AttributeError: pass return output_capabilities def action__status(self, request, *args, **kwargs): """ Reports the status of the RGB LED strip """ return { "current": self.led_strip.hex, "contrast": self.led_strip.contrast_from_bg(self.led_strip.hex, dark_default="202020"), "current_rgb": "({})".format(self.led_strip) } def teardown(self): """ Called automatically when exiting the parent reactor """ self.led_strip.teardown()
print('exiting') self.kill_now = True def set_color(strip): now = datetime.datetime.now() if now.time() < datetime.time(12): strip.set_morning_color() else: strip.set_evening_color() def run(strip): print('running') if __name__ == '__main__': killer = GracefulKiller() strip = LEDStrip() try: set_color(strip) while not killer.kill_now: run(strip) time.sleep(10) except Exception as ex: print(ex) strip.switch_off() strip.switch_off()
from helpers import * import pycom from network import WLAN from machine import Pin, Timer from _thread import start_new_thread import utime from ledstrip import LEDStrip pycom.heartbeat(False) import usocket as socket ledstrip = LEDStrip(Pin('P22'), Pin('P21'), Pin('P23')) pir = Pin('P18', mode=Pin.IN, pull=None) fadeout_timer = None # Commands: # # WAT - get color + fader status # DIS - set color # FAD - enable/disable Fader def leds(port, ledstrip): s = socket.socket() ip_addr = WLAN().ifconfig()[0] s.bind((ip_addr, port)) s.listen() while True: machine.idle()
#!/usr/bin/python import time from ledstrip import LEDStrip CLK = 17 DAT = 18 strip = LEDStrip(CLK, DAT) print("Off") strip.setcolouroff() time.sleep(1) print("White") strip.setcolourwhite() time.sleep(1) print("Red") strip.setcolourred() time.sleep(1) print("Green") strip.setcolourgreen() time.sleep(1) print("Blue") strip.setcolourblue() time.sleep(1) print("RGB 128,128,0")
from ledstrip import LEDStrip import time import random CLK = 3 DAT = 2 strip = LEDStrip(CLK, DAT) print("Set Color to Red") for r in range(50, 100): strip.setcolourrgb(r, 0, 0) time.sleep(0.05) print("Set Color to Blue") for b in range(50, 100): strip.setcolourrgb(0, 0, b) time.sleep(0.05) print("Set Color to Green") for g in range(50, 100): strip.setcolourrgb(0, g, 0) time.sleep(0.05) for ra in range(50, 200): r = random.randint(0, 255) b = random.randint(0, 255) g = random.randint(0, 255) strip.setcolourrgb(r, g, b) time.sleep(0.50)