Group Details Private

administrators

Member List
  • RE: Background Service Stopping

    @Brad-Magri-Olson, thank you for reporting the issue.

    I'm on version 1.0.54 and so far I'm not able to reproduce the issue.

    Can you try upgrading to 1.0.54? I tried downgrading my agent and I still couldn't reproduce it.

    Also, can you tell me what background command you're running?
    Also, what antivirus software do you use? I wonder if that's killing the service.

    posted in General Discussion
  • RE: Email says command didn't run, but it did.

    @David-Coulson, I fixed it. Now you won't get these "TRIGGERcmd - Your command didn't run" emails if the trigger was from Home Assistant.

    05213127-87ef-4be4-8f7a-ca4b3ae145f3-image.png

    Thanks again for reporting the problem.

    posted in General Discussion
  • RE: TRIGGERcmd setup on Google Assistant

    @Nuno-Gomes, thanks for telling me. Please try again. It should work now.

    posted in Google Home
  • RE: Firest time setting up, oauth failure

    @Asit-Mishra, thanks for telling me. Please try again. It should work now.

    posted in General Discussion
  • RE: How to use Off Command

    @Yoni, thanks for letting me know. I'll make it case-insensitive in the next version.

    posted in Instructions
  • RE: I want to be able to trigger an Alexa routine from a command line with the triggercmdagent installed on my Raspberry Pi

    I use CMDNOWND for this. https://dennisbabkin.com/cmdnownd/

    You pop it in the cmd line like this: cmdnownd "D:\Libraries\Documents\batchfile.bat" and it suppresses the appearance of the cmd window. Just place the exe in your path. I keep it in the Windows folder itself.
    scrsht_cmdnownd.png

    posted in Raspberry Pi
  • RE: I want to be able to trigger an Alexa routine from a command line with the triggercmdagent installed on my Raspberry Pi

    @Matt-Lodder, what OS are you running? I just tried echo on my Windows laptop and it did not pop up a window.

    posted in Raspberry Pi
  • RE: Email says command didn't run, but it did.

    @David-Coulson, I'll look into it.

    One thing you can check in the meantime make sure this checkbox is unchecked in your profile:

    fa9d5c2b-e823-4313-b84c-7c27e2afd8fa-image.png

    Can you show me one of the emails? I wonder if it's reminding you to subscribe because you're running more than 1 command per minute. I'll add an option to disable those emails too.

    Also, did you enable "Home Assistant Offline Configuration"?

    EDIT: I added this checkbox that you can uncheck to stop the subscription reminder emails:

    9edb18d9-cec9-4ebf-92ac-a40b6612bfbe-image.png

    posted in General Discussion
  • Python script to change my wifi color LED light bulb state

    My PC talks to my wifi light bulb directly, not via Tuya's cloud API.

    I can say, "Alexa, bulb 1 red" or "Alexa bulb 1 off" etc.

    I can also say, "Use @TRIGGERcmd to turn bulb 1 blue" using the MCP tool with ChatGPT.

    Example commands:

    Turn the bulb on:

    python3 c:\tools\tuyabulb.py --id abcdefghijklmnop123456 --key "123456!@ABCcdefh" --ip 192.168.86.25 on
    

    Set the color to red:

    python3 c:\tools\tuyabulb.py --id abcdefghijklmnop123456 --key "123456!@ABCcdefh" --ip 192.168.86.25 red
    

    Set the brightness to 60 percent:

    python3 c:\tools\tuyabulb.py --id abcdefghijklmnop123456 --key "123456!@ABCcdefh" --ip 192.168.86.25 60
    

    Here's the script:

    #!/usr/bin/env python3
    import argparse
    import ipaddress
    import platform
    import subprocess
    import sys
    import tinytuya
    
    # Predefined color presets (RGB values)
    COLOR_PRESETS = {
        "red": (255, 0, 0),
        "green": (0, 255, 0),
        "blue": (0, 0, 255),
        "white": (255, 255, 255),
        "yellow": (255, 255, 0),
        "cyan": (0, 255, 255),
        "magenta": (255, 0, 255),
        "orange": (255, 165, 0),
        "purple": (128, 0, 128),
        "pink": (255, 192, 203),
    }
    
    
    def ping_host(ip: str, timeout: int = 1) -> bool:
        """Ping a host to check if it's reachable. Returns True if ping succeeds."""
        param = "-n" if platform.system().lower() == "windows" else "-c"
        timeout_param = "-w" if platform.system().lower() == "windows" else "-W"
        timeout_value = str(timeout * 1000) if platform.system().lower() == "windows" else str(timeout)
        
        command = ["ping", param, "1", timeout_param, timeout_value, ip]
        try:
            result = subprocess.run(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=timeout + 1)
            return result.returncode == 0
        except (subprocess.TimeoutExpired, Exception):
            return False
    
    
    def make_device(device_id: str, ip: str, local_key: str, version: str | None):
        # BulbDevice works for most Tuya bulbs. If yours isn't a "bulb" type, use Device instead.
        d = tinytuya.BulbDevice(device_id, ip, local_key)
        d.set_socketPersistent(True)   # keep socket open for reliability
        d.set_socketTimeout(5)         # seconds
    
        # Many Tuya WiFi bulbs are 3.3. Some are 3.1. If you're unsure, try 3.3 first.
        if version:
            d.set_version(float(version))
        else:
            d.set_version(3.3)
    
        return d
    
    
    def main():
        p = argparse.ArgumentParser(description="Local control of a Tuya bulb via tinytuya (no cloud).")
        p.add_argument("--id", required=True, help="Tuya device id")
        p.add_argument("--ip", help="Bulb IP address on your LAN")
        p.add_argument("--subnet", help="Subnet to scan (e.g. 192.168.1.0/24)")
        p.add_argument("--start-from", help="IP address to start scanning from (only with --subnet)")
        p.add_argument("--key", required=True, help="Tuya localKey (16+ chars)")
        p.add_argument("--ver", default=None, help="Protocol version (e.g. 3.3 or 3.1). Default: 3.3")
        p.add_argument("cmd", help="Command: off, on, status, color name (red, green, etc.), or brightness 0-100")
        args = p.parse_args()
    
        # Determine command type
        cmd_lower = args.cmd.lower()
        if cmd_lower in ["off", "on", "status"]:
            cmd_type = cmd_lower
        elif cmd_lower in COLOR_PRESETS:
            cmd_type = "color"
            preset_color = cmd_lower
        elif args.cmd.isdigit():
            brightness_val = int(args.cmd)
            if 0 <= brightness_val <= 100:
                cmd_type = "brightness"
            else:
                p.error("Brightness must be between 0-100")
        else:
            p.error(f"Invalid command: {args.cmd}. Use: off, on, status, color name, or brightness (0-100)")
    
        # Validate that either --ip or --subnet is provided
        if not args.ip and not args.subnet:
            p.error("Either --ip or --subnet must be specified")
        if args.ip and args.subnet:
            p.error("Cannot specify both --ip and --subnet")
        if args.start_from and not args.subnet:
            p.error("--start-from can only be used with --subnet")
    
        # Determine which IPs to try
        if args.subnet:
            try:
                network = ipaddress.ip_network(args.subnet, strict=False)
                all_ips = [str(ip) for ip in network.hosts()]
                
                # Filter to start from specified IP if provided
                if args.start_from:
                    start_ip = ipaddress.ip_address(args.start_from)
                    # Verify start IP is in the subnet
                    if start_ip not in network:
                        print(f"ERROR: Start IP {args.start_from} is not in subnet {args.subnet}", file=sys.stderr)
                        return 1
                    # Filter to IPs >= start_from
                    ips_to_try = [ip for ip in all_ips if ipaddress.ip_address(ip) >= start_ip]
                    print(f"Scanning subnet {args.subnet} from {args.start_from} ({len(ips_to_try)} hosts)...", file=sys.stderr)
                else:
                    ips_to_try = all_ips
                    print(f"Scanning subnet {args.subnet} ({len(ips_to_try)} hosts)...", file=sys.stderr)
            except ValueError as e:
                print(f"ERROR: Invalid subnet or IP format: {e}", file=sys.stderr)
                return 1
        else:
            ips_to_try = [args.ip]
    
        # Try each IP until one works
        last_error = None
        for ip in ips_to_try:
            if args.subnet:
                print(f"Trying {ip}...", file=sys.stderr)
                # Quick ping check to skip unreachable hosts
                if not ping_host(ip):
                    continue
            
            dev = make_device(args.id, ip, args.key, args.ver)
    
            dev = make_device(args.id, ip, args.key, args.ver)
    
            try:
                if cmd_type == "off":
                    r = dev.turn_off()
                elif cmd_type == "on":
                    r = dev.turn_on()
                elif cmd_type == "brightness":
                    r = dev.set_brightness_percentage(brightness_val)
                elif cmd_type == "color":
                    # Get RGB values from preset
                    rgb = COLOR_PRESETS[preset_color]
                    # Set the color
                    r = dev.set_colour(rgb[0], rgb[1], rgb[2])
                else:
                    r = dev.status()
    
                # Check if the device responded with an errora
                if isinstance(r, dict) and r.get("Error"):
                    if args.subnet:
                        # During subnet scan, continue to next IP on error
                        last_error = r.get("Error")
                        continue
                    else:
                        # For direct IP, print error and exit
                        print(r)
                        return 2
    
                # Success! Print result and exit
                if args.subnet:
                    print(f"SUCCESS: Device found at {ip}", file=sys.stderr)
                print(r)
                return 0
    
            except Exception as e:
                last_error = e
                if not args.subnet:
                    print(f"ERROR: {e}", file=sys.stderr)
                    return 1
                # For subnet scan, continue to next IP
                continue
            finally:
                try:
                    dev.set_socketPersistent(False)
                except Exception:
                    pass
    
        # If we get here with subnet scan, none of the IPs worked
        if args.subnet:
            print(f"ERROR: Device not found in subnet {args.subnet}. Last error: {last_error}", file=sys.stderr)
            return 1
    
    
    if __name__ == "__main__":
        raise SystemExit(main())
    

    This is my commands.json entry:

     {
      "trigger": "Tuya Bulb 1",
      "command": "python3 c:\\tools\\tuyabulb.py --id abcdefghijklmnop123456 --key \"123456!@ABCcdefh\" --ip 192.168.86.25",
      "offCommand": "",
      "ground": "foreground",
      "voice": "bulb 1",
      "voiceReply": "",
      "allowParams": "true",
      "mcpToolDescription": "Controls the state of light bulb 1.  Parameters are: on, off, red, green, blue, white, yellow, cyan, magenta, orange, purple, pink, or brightness percentage from 0 to 100"
     }
    
    posted in Windows
  • RE: Unable to Subscribe - Link Appears to be Broken

    @Timothy-Martin, please try again. It should work now. Thanks again for telling me it was broken.

    posted in General Discussion