this post was submitted on 06 May 2024
36 points (95.0% liked)

Trees

6775 readers
2 users here now

A community centered around cannabis.

In the spirit of making Trees a welcoming and uplifting place for everyone, please follow our Commandments.

  1. Be Cool.
  2. I'm not kidding. Be nice to each other.
  3. Avoid low-effort posts

founded 2 years ago
MODERATORS
 

There's a vaporent community and a vaporists community. Neither have been active for almost a year. It would be nice to have one of those going to see what everybody's using. I also miss the old old cult/ Franklin/thca groups from r/. Anyone interested in starting one of those?

all 28 comments
sorted by: hot top controversial new old
[–] JTskulk 16 points 7 months ago (4 children)

I have a volcano and a script I wrote to control it via a tasmota power plug. Now my computer plays a clip of snoop dogg when I turn it on and when it's fully heated up. And it automatically turns it off at night if I forget to. I can turn it on from anywhere in the world. I think it's cool, but who cares?

[–] [email protected] 8 points 7 months ago (1 children)

I think it’s cool, but who cares?

We do! Please open-source it, king of stoner engineering!

(I use the Plenty from time to time, but it kinda sucks)

[–] JTskulk 2 points 7 months ago (1 children)

Ask and ye shall receive! I'm tacking a GPL 3 license to it. The plugs that play a sound after a delay won't work on Windows because I use fork(), but I don't use Windows because fuck Windows. It uses mpv to play sounds, but that is easily changed. AMA.

#!/usr/bin/env python
"Control my various tasmota devices. Licensed under GPL v3: https://www.gnu.org/licenses/gpl-3.0.en.html#license-text"

import os
from time import sleep
import urllib.request
from json import loads
from subprocess import Popen

__all__ = ["Tasmota", "TasmotaWarmup", "TasmotaOffFirst", "DEVICENAMES"]

class Tasmota():
    "A tasmota device."
    def __init__(self, ipaddress: str, name: str=None):
        self.ipaddress = ipaddress
        self.name = name

    def __repr__(self):
        return f"<{type(self).__name__} {self.name if self.name else self.ipaddress}>"

    def _request(self, cmd: str) -> str:
        "make an http request to the device"
        return urllib.request.urlopen(f"http://{self.ipaddress}/cm?cmnd={cmd.replace(' ', '%20')}").read()

    def on(self) -> bool:
        "Turn the device on. return True if successful"
        return b"ON" in self._request("Power On")

    def off(self) -> bool:
        "Turn the device off. return True if successful"
        return b"OFF" in self._request("Power Off")

    def toggle(self) -> bool:
        "Toggle the device power. return True if power is now on, False if it's off"
        return b"ON" in self._request("Power Toggle")

    def status(self) -> bool:
        "return True if the device is on, False if it is off"
        return bool(loads(self._request("Status"))["Status"]["Power"])

class TasmotaWarmup(Tasmota):
    "Plays a sound when started, plays a sound after a waiting period."
    def __init__(self, ipaddress: str, name: str=None, warmup_time: int=None, on_sound: str=None, ready_sound: str=None):
        "warmup_time is seconds, on/ready_sound is the path to the audio file to play"
        super().__init__(ipaddress, name)
        self.warmup_time = warmup_time
        self.on_sound = on_sound
        self.ready_sound = ready_sound

    def _playSound(self, sound: str) -> None:
        "play a sound"
        Popen(["mpv", "--no-terminal", "--volume=60", sound])

    def _beginPowerOnSounds(self) -> None:
        "Play a sound when turning on and another sound when ready"
        if self.on_sound:
                self._playSound(self.on_sound)
        if self.warmup_time and self.ready_sound:
            if __name__ == "__main__": # using this as a script, fork to background and return terminal
                if os.fork() == 0: # wait in the background for the warmup_time
                    self._sleepAndPlay()
                    raise SystemExit
            else:
                Thread(target=self._sleepAndPlay).start()

    def _sleepAndPlay(self) -> None:
        "The actual sleeping and playing, to be run in a thread if needed."
        sleep(self.warmup_time)
        if self.status(): # if device is still on
            self._playSound(self.ready_sound)

    def on(self) -> bool:
        "Turn the device on and play sounds"
        if super().on():
            self._beginPowerOnSounds()
            return True
        return False

    def toggle(self) -> bool:
        "toggle the status and play sounds if we're turning it on"
        if super().toggle():
            self._beginPowerOnSounds()
            return True
        return False

class TasmotaOffFirst(TasmotaWarmup):
    "A Tasmota object that turns the device off first before turning it on"
    def _turn_off_before_on(self) -> bool:
        "Turn this device off first if it's already on when it's switched on"
        if not super().toggle(): # if toggling turned it off
            super().on()
        return True

    def on(self) -> bool:
        return self._turn_off_before_on()

class TasmotaAlwaysOn(TasmotaOffFirst):
    "This Tasmota class is always on; toggling it will turn it off briefly and then back on"
    def toggle(self) -> bool:
        "toggle this device off and then back on again"
        return self._turn_off_before_on()

DEVICENAMES = {"volcano": TasmotaWarmup("192.168.1.152", "Volcano", 355, "/home/jt/.sounds/hold up hey.ogg",
                                        "/home/jt/.sounds/fill that bag up right now2.flac"),
                   "towel": TasmotaOffFirst("192.168.1.153", "Towel Warmer", warmup_time=(20*60)+30,
                                            ready_sound="/home/jt/.sounds/yayeah.ogg"),
                   "radiator": Tasmota("192.168.1.166", "Radiator"),
                   "taco": TasmotaAlwaysOn("192.168.1.156", "Taco")
                   }

if __name__ != "__main__":
    from threading import Thread # only needed when importing this module
else:
    import sys, argparse
    parser = argparse.ArgumentParser(description="Control Tasmota wifi power plugs")
    parser.add_argument("devices", help="device(s)", action="store", nargs="*")
    operation_group = parser.add_mutually_exclusive_group()
    operation_group.add_argument('--on', '-n', help="power on device", action="store_true")
    operation_group.add_argument('--off', '-f', help="power off device", action="store_true")
    operation_group.add_argument('--toggle', '-t', help="toggle device power", action="store_true")
    operation_group.add_argument('--status', '-s', help="get status of device", action="store_true")
    args = parser.parse_args()

    # Sanity checks
    if not args.devices:
        print(f"No device specified. Available devices are: {' '.join(DEVICENAMES.keys())}", file=sys.stderr)
        parser.print_help()
        sys.exit(1)
    invalid = []
    for d in args.devices:
        if not DEVICENAMES.get(d):
            invalid.append(d)
    if invalid:
        print(f"Invalid device{'s' if len(invalid) > 1 else ''}: {' '.join(invalid)}", file=sys.stderr)
        print(f"Available devices are: {' '.join(DEVICENAMES.keys())}", file=sys.stderr)
        sys.exit(3)
    for d in args.devices: # gogo
        t = DEVICENAMES[d]
        if args.on:
            if t.on():
                print(f"{t.name} turned on")
            else:
                print(f"Failed to turn on {t.name}", file=sys.stderr)
        elif args.off:
            if t.off():
                print(f"{t.name} turned off")
            else:
                print(f"Failed to turn off {t.name}", file=sys.stderr)
        elif args.toggle:
            print(f"{t.name} turned {'on' if t.toggle() else 'off'}")
        elif args.status:
            print(f"{t.name} is {'on' if t.status() else 'off'}")
[–] [email protected] 4 points 7 months ago (1 children)

That is wild, now I want a volcano. I'm more into handhelds and love my crafty+ but that's wild enough to make me think about buying one

[–] JTskulk 2 points 7 months ago

Dude honestly the Volcano rules. I've had mine almost 20 years now and I've had a screw rattle loose and the plastic airflow button broke ($10 part) and that's it. I also bought a Crafty+ and I hardly ever use it. The Volcano is definitely smoother and I think hits harder. Plus you can see how heavy your dose is about to be as the bag fills. The power plugs I bought came out to like $10 each I think for a pack of 4.

[–] Today 4 points 7 months ago (1 children)

That's crazy cool! Wouldn't mind seeing a pic or video.

[–] JTskulk 1 points 7 months ago

There's not much to see. I made this cool mollyguard for the power button out of a clear bud capsule. This way nobody flips the switch when I expect it to stay on all the time and I can see the power light through it.

Lemmy is failing to upload my images, so here's 2 links:

Volcano (excuse the mess, I found I spilled some inside last night and tried to clean it lol)

My dinky menu I use for it sometimes

[–] [email protected] 2 points 7 months ago (1 children)

I can turn it on from anywhere in the world. I think it's cool, but who cares?

Inb4 burglars care because it can be used to track when you're at home and when you're away on a holiday

I know the chances are far lower for custom stuff when compared to cheap IP cameras, but having anything open to the internet should leave you extra paranoid.

[–] JTskulk 2 points 7 months ago

It's actually not open on the internet, it's only on my LAN. I ssh in to access it if I'm out which is rare so it's very safe. These Tasmota plugs are great because they use Free software firmware (which I updated from the web, not the manufacturer), I trust them a lot more than any other IOT device.

[–] [email protected] 6 points 7 months ago

So start posting to vaporents instead of trying to make the 5th community on the same topic just because nobody posted in 3 months?

[–] [email protected] 4 points 7 months ago

Yes to both lol, the cult is toxic af but on Lemmy I think it'd be great! I've spent a frankly embarrassing amount on cult bud so I could contribute a shit ton to a cult community if we had one. I also try to keep up on the news for them and there would be 0 shilling here probably.

On to the vaporents side, I have a mighty+, (sadly collecting dust, I need to sell it so it gets used, great unit), a tinymight2, and I just pre-order the vapvana screwball that I am super excited for. So I could also make some OC content for that side but not nearly as much as a cult sub. Like you said that one's dead currently and I don't buy vapes like bud.

I suppose for now we could just do all of this on trees? I thought about it but I think long term it may be better to start these communities? Not sure TBH but I would love to see em both!

[–] [email protected] 4 points 7 months ago (1 children)

What are the Old old cult and Franklin?

[–] Today 6 points 7 months ago (1 children)

The thca subs from r/. 40% reviews and sales and 60% shit talking.

[–] [email protected] 3 points 7 months ago

Damn accurate description

[–] jadedwench 4 points 7 months ago (1 children)

I am still in love with my Mighty+. You can get a Titanium mouth piece that is pretty sweet, but the rubber to keep it from falling out is garbage. I wrapped a little bit of gaffers tape around it, and that works much better. Otherwise, I use the plastic one.

I am not the type to buy large collections of dry herb vapes, but ever since my state went legal, the bud must flow. 😁

[–] [email protected] 1 points 7 months ago (1 children)

For sure the best session portable vape currently, the Venty might be better? I don't own one and I probably won't because I like my TM2, but I have heard good things about it. I wouldn't buy it till the venty+ model releases if they do that because the venty does have some kinks currently.

[–] jadedwench 1 points 7 months ago

Yeah, I don't have any reason to switch either. It is so stoner friendly with the little vibration reminder, USB-C PD, and you can use it plugged in if you were dumb and never charged it. I am a simple woman. I do complicated shit all day at work, so the little things that should be simple can really matter to me.

[–] [email protected] 3 points 7 months ago (1 children)

Discord was the better community imo. The Frank tank. I’d love to see something flourish here!

[–] Today 3 points 7 months ago (1 children)

I couldn't get into discord because it seemed like you had to wade through pages of crap and jokes to get to real info. Maybe I'm doing it wrong?

[–] [email protected] 2 points 7 months ago (1 children)

That’s accurate and fair tbh.

[–] [email protected] 3 points 7 months ago

I also don’t get unwell with discord.

I have nothing against it, but the user interface just doesn’t work well with my psyche.